
// MFCD3D11TestView.cpp : implementation of the CMFCD3D11TestView class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "MFCD3D11Test.h"
#endif

#include "MFCD3D11TestDoc.h"
#include "MFCD3D11TestView.h"
#include "GlobalFunction.h"
#include "Utility/D3D/D3DUtilityFunction.h"
#include "Utility/UtilDefs.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMFCD3D11TestView

IMPLEMENT_DYNCREATE(CMFCD3D11TestView, CView)

BEGIN_MESSAGE_MAP(CMFCD3D11TestView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFCD3D11TestView::OnFilePrintPreview)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_MESSAGE(WM_RENDER, &CMFCD3D11TestView::OnRender)
	ON_WM_SETFOCUS()
	ON_COMMAND(ID_EDIT_RENDER3DOBJECT, &CMFCD3D11TestView::OnEditRender3dobject)
	ON_COMMAND(ID_EDIT_RENDERBRDF, &CMFCD3D11TestView::OnEditRenderbrdf)
	ON_WM_DESTROY()
	ON_COMMAND(ID_PLOT_1DNDFFUNC_Y, &CMFCD3D11TestView::OnPlot1dndffuncY)
	ON_COMMAND(ID_PLOT_1DNDFFUNC_X, &CMFCD3D11TestView::OnPlot1dndffuncX)
	ON_COMMAND(ID_EDIT_SHOW2DNDFPLOT, &CMFCD3D11TestView::OnEditShow2dndfplot)
	ON_COMMAND(ID_EDIT_SPLITCOLDIR, &CMFCD3D11TestView::OnEditSplitcoldir)
	ON_COMMAND(ID_EDIT_COMPUTENDFMULTIPLEFILES, &CMFCD3D11TestView::OnEditComputendfmultiplefiles)
	ON_COMMAND(ID_EDIT_SUBSTRACTFROMBIGNDF, &CMFCD3D11TestView::OnEditSubstractfrombigndf)
	ON_COMMAND(ID_EDIT_SPLITROWDIR, &CMFCD3D11TestView::OnEditSplitrowdir)
	ON_COMMAND(ID_EDIT_COMPUTENDFMULTIPLEFILESROWDIR, &CMFCD3D11TestView::OnEditComputendfmultiplefilesrowdir)
	ON_COMMAND(ID_EDIT_Plot1DNDFFunc_Y_LargeRegion, &CMFCD3D11TestView::OnEditPlot1dndffuncYLargeregion)
	ON_COMMAND(ID_EDIT_Plot1DNDFFunc_X_LargeRegion, &CMFCD3D11TestView::OnEditPlot1dndffuncXLargeregion)
	ON_COMMAND(ID_EDIT_COMPUTENDFMULTIPLEFILES8BY8, &CMFCD3D11TestView::OnEditComputendfmultiplefiles8by8)
	ON_COMMAND(ID_EDIT_SPLITINAARBITRARYSIZE, &CMFCD3D11TestView::OnEditSplitinaarbitrarysize)
	ON_COMMAND(ID_EDIT_SAVEASOBJFILE, &CMFCD3D11TestView::OnEditSaveasobjfile)
	//user defined messages
	ON_MESSAGE(WM_LOADXYZ_PROCESSING, OnLoadXYZProcessing)
	ON_MESSAGE(WM_LOADXYZ_FINISHED, OnLoadXYZFinished)
	ON_MESSAGE(WM_LOADXYZ_STARTED, OnLoadXYZStarted)
	ON_MESSAGE(WM_PROCESSXYZ_STARTED, OnProcessXYZStarted)
	ON_MESSAGE(WM_PROCESSXYZ_FINISHED, OnProcessXYZFinished)
	ON_MESSAGE(WM_PROCESSMULTIXYZ_STARTED, OnProcessMXYZStarted)
	ON_MESSAGE(WM_PROCESSMULTIXYZ_FINISHED, OnProcessMXYZFinished)
	ON_MESSAGE(WM_NORMALESTUPDATE_STARTED, OnNormEstUpdateStarted)
	ON_MESSAGE(WM_NORMALESTUPDATE_FINISHED, OnNormEstUpdateFinished)
	ON_MESSAGE(WM_RAYTRACINGHMSTAT_STARTED, OnRTHMStatStarted)
	ON_MESSAGE(WM_RAYTRACINGHMSTAT_FINISHED, OnRTHMStatFinished)
	ON_MESSAGE(WM_RAYTRACINGVGONIO_STARTED, OnRTVGonioStarted)
	ON_MESSAGE(WM_RAYTRACINGVGONIO_FINISHED, OnRTVGonioFinished)
	ON_MESSAGE(WM_COMPUTEWAVEOPTICBRDFSINGLEXYZ_STARTED, OnComputeWBRDFSingleXYZStarted)
	ON_MESSAGE(WM_COMPUTEWAVEOPTICBRDFSINGLEXYZ_FINISHED, OnComputeWBRDFSingleXYZFinished)
	ON_MESSAGE(WM_COMPUTEWAVEOPTICBRDFMULTIPLEXYZ_STARTED, OnComputeWBRDFMultipleXYZStarted)
	ON_MESSAGE(WM_COMPUTEWAVEOPTICBRDFMULTIPLEXYZ_FINISHED, OnComputeWBRDFMultipleXYZFinished)

	ON_MESSAGE(WM_RAYTRACINGVGONIOMFILES_STARTED, OnRTVGonioMFilesStarted)
	ON_MESSAGE(WM_RAYTRACINGVGONIOMFILES_FINISHED, OnRTVGonioMFilesFinished)

	ON_COMMAND(ID_EDIT_ComputeNDFMultipleFilesGeneral, &CMFCD3D11TestView::OnEditComputendfmultiplefilesgeneral)
	ON_COMMAND(ID_EDIT_SHOW2DHEIGHTMAPBMP, &CMFCD3D11TestView::OnEditShow2dheightmapbmp)	
	ON_COMMAND(ID_EDIT_PLOT1DSLICEHEIGHT_Y, &CMFCD3D11TestView::OnEditPlot1dsliceheightY)
	ON_COMMAND(ID_EDIT_PLOT1DSLICEHEIGHT_X, &CMFCD3D11TestView::OnEditPlot1dsliceheightX)
	ON_COMMAND(ID_RayTracingStatisticalTest, &CMFCD3D11TestView::OnRaytracingstatisticaltest)
	ON_COMMAND(ID_EDIT_RAYTRACINGVIRTUALGONIOTEST, &CMFCD3D11TestView::OnEditRaytracingvirtualgoniotest)
	ON_COMMAND(ID_EDIT_RayTracingVirtualGonioTest_MFiles, &CMFCD3D11TestView::OnEditRaytracingvirtualgoniotestMfiles)
	ON_COMMAND(ID_EDIT_SHOW2DNDFPLOT_LARGEREGION, &CMFCD3D11TestView::OnEditShow2dndfplotLargeregion)
	ON_COMMAND(ID_EDIT_DEBUGNDFELLIPSOID, &CMFCD3D11TestView::OnEditDebugndfellipsoid)
	ON_COMMAND(ID_EDIT_DEBUGSINCOSWAVE, &CMFCD3D11TestView::OnEditDebugsincoswave)
	ON_COMMAND(ID_EDIT_GENERATEXYZFILEFROMAFM1DSLICES, &CMFCD3D11TestView::OnEditGeneratexyzfilefromafm1dslices)
	ON_COMMAND(ID_EDIT_COMPUTEWAVEOPTICSBRDF, &CMFCD3D11TestView::OnEditComputewaveopticsbrdf)
	ON_COMMAND(ID_EDIT_COMPUTEWAVEOPTICSBRDF_MFILES, &CMFCD3D11TestView::OnEditComputewaveopticsbrdfMfiles)
	ON_COMMAND(ID_EDIT_PLOTWAVEOPTICBRDFCOMP, &CMFCD3D11TestView::OnEditPlotwaveopticbrdfcomp)
	ON_COMMAND(ID_EDIT_LOADPRECOMPUTEDWAVEOPTICBRDF, &CMFCD3D11TestView::OnEditLoadprecomputedwaveopticbrdf)
	ON_COMMAND(ID_EDIT_GENERATEPLANARXYZFILE, &CMFCD3D11TestView::OnEditGenerateplanarxyzfile)
	ON_COMMAND(ID_EDIT_RAYTRACING1DSLICESEG, &CMFCD3D11TestView::OnEditRaytracing1dsliceseg)
END_MESSAGE_MAP()

// CMFCD3D11TestView construction/destruction

CMFCD3D11TestView::CMFCD3D11TestView(): m_bAvg1DNDF(false), m_lPercentDisplay(0), m_iCurHeightBMPDir(Y_DIR), m_fAlphaX_AGGX(0.5), 
	m_fAlphaY_AGGX(0.5), m_fScalingFactor_AGGX(1.0), m_fAdjustScalingFactor(1.0), m_iHMDataWidth(640), m_iHMDataHeight(480), 
	m_fDataPSize_x(70), m_fDataPSize_y(55)
{
	// TODO: add construction code here	
}

CMFCD3D11TestView::~CMFCD3D11TestView()
{
}

BOOL CMFCD3D11TestView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// CMFCD3D11TestView drawing

void CMFCD3D11TestView::OnDraw(CDC* pDC)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
}


// CMFCD3D11TestView printing


void CMFCD3D11TestView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
	AFXPrintPreview(this);
#endif
}

BOOL CMFCD3D11TestView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMFCD3D11TestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMFCD3D11TestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CMFCD3D11TestView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMFCD3D11TestView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CMFCD3D11TestView diagnostisc

#ifdef _DEBUG
void CMFCD3D11TestView::AssertValid() const
{
	CView::AssertValid();
}

void CMFCD3D11TestView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCD3D11TestDoc* CMFCD3D11TestView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCD3D11TestDoc)));
	return (CMFCD3D11TestDoc*)m_pDocument;
}
#endif //_DEBUG

int CMFCD3D11TestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

#define  ID_TMP  144444
	if(!m_D3DWnd.Create(NULL, NULL, WS_CHILD|WS_VISIBLE, CRect(0,0,10,10), this, ID_TMP))
		return -1;

	if(!m_dlg3DObjectRendering.Create(IDD_DIALOG_3DOBJECT))
		return -1;

	if(!m_dlgBRDFRendering.Create(IDD_DIALOG_RENDER))
		return -1;

	if(!m_dlg2DNDFVisual.Create(IDD_BMP))
		return -1;

	if(!m_dlg2dHeightBMP.Create(IDD_HEIGHTBMP))
		return -1;
	
	return 0;
}


void CMFCD3D11TestView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here
	if(m_D3DWnd.GetSafeHwnd() && nType != SIZE_MINIMIZED)
	{
		m_D3DWnd.SetWindowPos(&CWnd::wndTop, 0, 0, cx, cy, SWP_NOMOVE);
	}
}

LRESULT CMFCD3D11TestView::OnRender(WPARAM,LPARAM)
{
	m_D3DWnd.SendMessage(WM_RENDER);
	return 0;
}

void CMFCD3D11TestView::OnSetFocus(CWnd* pOldWnd)
{
	CView::OnSetFocus(pOldWnd);

	// TODO: Add your message handler code here
	if(m_D3DWnd.GetSafeHwnd())
		m_D3DWnd.SetFocus();
}


void CMFCD3D11TestView::OnInitialUpdate()
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CView::OnInitialUpdate();
}

void CMFCD3D11TestView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
	// TODO: Add your specialized code here and/or call the base class
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	{
		float fWidth = pDoc->GetXYZFile()->m_fSampleWidth;
		float fHeight = pDoc->GetXYZFile()->m_fSampleHeight;
		unsigned int iHMWidth = pDoc->GetXYZFile()->m_iHMDataWidth;
		unsigned int iHMHeight = pDoc->GetXYZFile()->m_iHMDataHeight;

		CMFCPropertyGridProperty* pXYZDimProperty = theApp.GetPropertyGridCtrl()->GetProperty(0);
		CMFCPropertyGridProperty* pXYZDimPropertyWidth = pXYZDimProperty->GetSubItem(0);
		pXYZDimPropertyWidth->SetValue(fWidth);
		CMFCPropertyGridProperty* pXYZDimPropertyHeight = pXYZDimProperty->GetSubItem(1);
		pXYZDimPropertyHeight->SetValue(fHeight);
		CMFCPropertyGridProperty* pXYZDimPropertyHMWidth = pXYZDimProperty->GetSubItem(2);
		pXYZDimPropertyHMWidth->SetValue((_variant_t)(unsigned int)iHMWidth);
		CMFCPropertyGridProperty* pXYZDimPropertyHMHeight = pXYZDimProperty->GetSubItem(3);
		pXYZDimPropertyHMHeight->SetValue((_variant_t)(unsigned int)iHMHeight);


		CRenderHeightMap* pRenderHMTech = m_D3DWnd.GetRenderHMTech();
		if(pRenderHMTech)
		{
			CMFCPropertyGridProperty* pXYZRenderProperty = theApp.GetPropertyGridCtrl()->GetProperty(1);
			CMFCPropertyGridColorProperty* pNormalColor = static_cast<CMFCPropertyGridColorProperty*>(pXYZRenderProperty->GetSubItem(0));

			D3DXVECTOR4 color = pRenderHMTech->GetNormalLineColor();
			byte r = static_cast<byte>(ceil(color.x * 255));
			byte g = static_cast<byte>(ceil(color.y * 255));
			byte b = static_cast<byte>(ceil(color.z * 255));
			pNormalColor->SetColor(RGB(r,g,b));
			
			CMFCPropertyGridProperty* pBoolShowLine = pXYZRenderProperty->GetSubItem(1);
			bool bShowLine = pRenderHMTech->GetbRenderNormal();
			pBoolShowLine->SetValue((_variant_t)bShowLine);

			CMFCPropertyGridProperty* pNormalLineScale = pXYZRenderProperty->GetSubItem(2);
			float fNormalLineScale= pRenderHMTech->GetNormalLineScale();
			long iNormalLineScale = static_cast<long>(floor(fNormalLineScale*100));
			pNormalLineScale->SetValue(iNormalLineScale);

			CMFCPropertyGridProperty* pBoolWireFrame = pXYZRenderProperty->GetSubItem(3);
			bool bWF = pRenderHMTech->GetbRenderWF();
			pBoolWireFrame->SetValue((_variant_t)bWF);


			CMFCPropertyGridProperty* pXYZNormalProperty = theApp.GetPropertyGridCtrl()->GetProperty(2);

			CMFCPropertyGridProperty* pCurNormalMethod = pXYZNormalProperty->GetSubItem(0);
			NORMALESTIMATEMETHOD iCurMethod = pRenderHMTech->GetCurXYZFile()->GetCurNormalEstiMethod();
			switch(iCurMethod)
			{
			case  USEWEIGHTEDPCA_GAUSSIAN:
				pCurNormalMethod->SetValue(_T("LS PCA Gauss"));
				break;
			case USEPCANORMAL:
				pCurNormalMethod->SetValue(_T("LS PCA"));
				break;
			case USEAREAWEIGHTEDNORMAL:
				pCurNormalMethod->SetValue(_T("TriArea Avg"));
				break;
			}

			CMFCPropertyGridProperty* pNormalWndSize = pXYZNormalProperty->GetSubItem(1);
			long iNormalWndSize = pRenderHMTech->GetNormalWndSize();
			pNormalWndSize->SetValue(iNormalWndSize);
			if(iCurMethod == USEPCANORMAL)
				pNormalWndSize->EnableSpinControl(TRUE, 3, 99);
			else
				pNormalWndSize->EnableSpinControl(FALSE);
			

			CMFCPropertyGridProperty* pNFGaussianSigma = pXYZNormalProperty->GetSubItem(2);
			float fGaussianSigma = pRenderHMTech->GetNFGaussianSigma();
			long iGaussianSigma = static_cast<long>(floor(fGaussianSigma));
			pNFGaussianSigma->SetValue(iGaussianSigma);
			if(iCurMethod == USEWEIGHTEDPCA_GAUSSIAN)
				pNFGaussianSigma->EnableSpinControl(TRUE, 1, 100);
			else
				pNFGaussianSigma->EnableSpinControl(FALSE);

			CMFCPropertyGridProperty* pCurGonioDir = pXYZNormalProperty->GetSubItem(3);
			GONIOAXIS iCurGonioAxis = pDoc->GetXYZFile()->GetCurGonioDir();
			switch(iCurGonioAxis)
			{
			case  MAJORAXIS:
				pCurGonioDir->SetValue(_T("MAJORAXIS"));
				break;
			case MINORAXIS:
				pCurGonioDir->SetValue(_T("MINORAXIS"));
				break;			
			}			

			
			CMFCPropertyGridProperty* pDisp2DNDFProperty = theApp.GetPropertyGridCtrl()->GetProperty(3);
			
			CMFCPropertyGridProperty* pBoolbAvg1DNDF = pDisp2DNDFProperty->GetSubItem(0);
			bool bAvg = m_bAvg1DNDF;
			pBoolbAvg1DNDF->SetValue((_variant_t)bAvg);

			CMFCPropertyGridProperty* pRTHMProperty = theApp.GetPropertyGridCtrl()->GetProperty(4);
			CMFCPropertyGridProperty* pfRTHMScaleRatio = pRTHMProperty->GetSubItem(0);
			long iScaleRatio = static_cast<long>(pDoc->getRTScaleRatio()*100);
			pfRTHMScaleRatio->SetValue((_variant_t)iScaleRatio);

			CMFCPropertyGridProperty* pfRTHMThetaAng = pRTHMProperty->GetSubItem(1);
			long iThetaAng = static_cast<long>(pDoc->getRTThetaAng());
			pfRTHMThetaAng->SetValue((_variant_t)iThetaAng);

			CMFCPropertyGridProperty* pfRTHMPhiAng = pRTHMProperty->GetSubItem(2);
			long iPhiAng = static_cast<long>(pDoc->getRTPhiAng());
			pfRTHMPhiAng->SetValue((_variant_t)iPhiAng);

			CMFCPropertyGridProperty* pFresnelReal = pRTHMProperty->GetSubItem(3);
			double fFresnelReal = pDoc->GetXYZFile()->getFresnelIORReal();
			pFresnelReal->SetValue((_variant_t) (double) fFresnelReal);

			CMFCPropertyGridProperty* pFresnelImg = pRTHMProperty->GetSubItem(4);
			double fFresnelImg = pDoc->GetXYZFile()->getFresnelIORImg();
			pFresnelImg->SetValue((_variant_t) (double) fFresnelImg);

			CMFCPropertyGridProperty* pEllipsoidNDFParams = theApp.GetPropertyGridCtrl()->GetProperty(5);
			CMFCPropertyGridProperty* pAlphaX_AGGX = pEllipsoidNDFParams->GetSubItem(0);
			pAlphaX_AGGX->SetValue((_variant_t)(double)m_fAlphaX_AGGX);

			CMFCPropertyGridProperty* pAlphaY_AGGX = pEllipsoidNDFParams->GetSubItem(1);
			pAlphaY_AGGX->SetValue((_variant_t)(double)m_fAlphaY_AGGX);

			CMFCPropertyGridProperty* pScalingFactor_AGGX = pEllipsoidNDFParams->GetSubItem(2);
			pScalingFactor_AGGX->SetValue((_variant_t)(double)m_fScalingFactor_AGGX);

			CMFCPropertyGridProperty* pAdjustScaleFactor = pEllipsoidNDFParams->GetSubItem(3);
			pAdjustScaleFactor->SetValue((_variant_t)(double)m_fAdjustScalingFactor);

			CMFCPropertyGridProperty* pHMWidth = pEllipsoidNDFParams->GetSubItem(4);
			pHMWidth->SetValue((_variant_t)(unsigned int)m_iHMDataWidth);
			
			CMFCPropertyGridProperty* pHMHeight = pEllipsoidNDFParams->GetSubItem(5);
			pHMHeight->SetValue((_variant_t)(unsigned int)m_iHMDataHeight);
			
			CMFCPropertyGridProperty* pDataPSizeX = pEllipsoidNDFParams->GetSubItem(6);
			pDataPSizeX->SetValue((_variant_t)(double)m_fDataPSize_x);
			
			CMFCPropertyGridProperty* pDataPSizeY = pEllipsoidNDFParams->GetSubItem(7);
			pDataPSizeY->SetValue((_variant_t)(double)m_fDataPSize_y);
		}
	}
	
	CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}

void CMFCD3D11TestView::queryXYZNormEstParamsFromUI(NORMALESTIMATEMETHOD& iCurEstMethod, int& iKernelSize, float& fGaussianSigma)
{
	CMFCPropertyGridProperty* pXYZNormalProperty = theApp.GetPropertyGridCtrl()->GetProperty(2);
	CMFCPropertyGridProperty* pCurNormalMethod = pXYZNormalProperty->GetSubItem(0);
	CString strTmp = pCurNormalMethod->GetValue();
	if(strTmp.Compare(_T("LS PCA")) == 0)
		iCurEstMethod = USEPCANORMAL;
	else if(strTmp.Compare(_T("LS PCA Gauss")) == 0)
		iCurEstMethod = USEWEIGHTEDPCA_GAUSSIAN;
	else if(strTmp.Compare(_T("TriArea Avg")) == 0)
		iCurEstMethod = USEAREAWEIGHTEDNORMAL;
	else 
		return;

	CMFCPropertyGridProperty* pNFKernelSize = pXYZNormalProperty->GetSubItem(1);
	iKernelSize = pNFKernelSize->GetValue().intVal;

	CMFCPropertyGridProperty* pNFGaussianSigma = pXYZNormalProperty->GetSubItem(2);
	int iVal = pNFGaussianSigma->GetValue().intVal;
	fGaussianSigma = static_cast<float>(iVal);
	
}

void CMFCD3D11TestView::OnEditRender3dobject()
{
	// TODO: Add your command handler code here
	m_dlg3DObjectRendering.ShowWindow(SW_SHOW);

	//move the window
	//query monitor info
	CArray<CRect> arrDisp;
	GetDisplays(arrDisp);
	unsigned int iIdxRectMainMon;
	CArray<unsigned int> iArrIdxRectMinorMon;
	for(unsigned int iMon=0; iMon<arrDisp.GetSize();iMon++)
	{
		if(arrDisp[iMon].left == 0)
			iIdxRectMainMon = iMon;
		else
			iArrIdxRectMinorMon.Add(iMon);

	}
	if(arrDisp.GetSize()>1)
	{
		//move the window
		CRect curRect;
		m_dlg3DObjectRendering.GetWindowRect(&curRect);
		CRect mainWndRect;
		GetWindowRect(&mainWndRect);

		HMONITOR hMonitor;
		MONITORINFO mi;
		// get the nearest monitor to the passed rect. 
		hMonitor = MonitorFromRect(mainWndRect, MONITOR_DEFAULTTONEAREST);
		// get the work area or entire monitor rect. 
		mi.cbSize = sizeof(mi);
		GetMonitorInfo(hMonitor, &mi);
		bool bMainMon = true;
		if(mi.rcMonitor.left>0)
			bMainMon = false;

		CRect newRect = curRect;
		if(bMainMon)
		{
			//use the first minor monitor
			unsigned int iMinorMon = iArrIdxRectMinorMon[0];
			newRect.left = arrDisp[iMinorMon].left;
			newRect.right = newRect.left+curRect.Width();	
		}
		else
		{
			//use the main monitor
			newRect.left = arrDisp[iIdxRectMainMon].left;
			newRect.right = newRect.left+curRect.Width();	
		}		
		m_dlg3DObjectRendering.MoveWindow(newRect,FALSE);
	}
}


void CMFCD3D11TestView::OnEditRenderbrdf()
{
	// TODO: Add your command handler code here
	m_dlgBRDFRendering.ShowWindow(SW_SHOW);

	//move the window
	//query monitor info
	CArray<CRect> arrDisp;
	GetDisplays(arrDisp);
	unsigned int iIdxRectMainMon;
	CArray<unsigned int> iArrIdxRectMinorMon;
	for(unsigned int iMon=0; iMon<arrDisp.GetSize();iMon++)
	{
		if(arrDisp[iMon].left == 0)
			iIdxRectMainMon = iMon;
		else
			iArrIdxRectMinorMon.Add(iMon);

	}
	if(arrDisp.GetSize()>1)
	{
		//move the window
		CRect curRect;
		m_dlg3DObjectRendering.GetWindowRect(&curRect);
		CRect mainWndRect;
		GetWindowRect(&mainWndRect);

		HMONITOR hMonitor;
		MONITORINFO mi;
		// get the nearest monitor to the passed rect. 
		hMonitor = MonitorFromRect(mainWndRect, MONITOR_DEFAULTTONEAREST);
		// get the work area or entire monitor rect. 
		mi.cbSize = sizeof(mi);
		GetMonitorInfo(hMonitor, &mi);
		bool bMainMon = true;
		if(mi.rcMonitor.left>0)
			bMainMon = false;

		CRect newRect = curRect;
		CRect ObjWndRect;
		m_dlg3DObjectRendering.GetWindowRect(&ObjWndRect);
		if(bMainMon)
		{
			//use the first minor monitor
			unsigned int iMinorMon = iArrIdxRectMinorMon[0];
			newRect.left = arrDisp[iMinorMon].left+ObjWndRect.Width();
			newRect.right = newRect.left+curRect.Width();	
		}
		else
		{
			//use the main monitor
			newRect.left = arrDisp[iIdxRectMainMon].left+ObjWndRect.Width();
			newRect.right = newRect.left+curRect.Width();	
		}		
		m_dlgBRDFRendering.MoveWindow(newRect,FALSE);
	}

}


void CMFCD3D11TestView::OnDestroy()
{
	CView::OnDestroy();

	// TODO: Add your message handler code here
    m_dlg3DObjectRendering.DestroyWindow();
	m_dlgBRDFRendering.DestroyWindow();
	m_dlg2DNDFVisual.DestroyWindow();
	m_dlg2dHeightBMP.DestroyWindow();
}


void CMFCD3D11TestView::OnPlot1dndffuncY()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		pXYZFile->SetCurNDFGenDir(YDIR);
		pXYZFile->SetCurGonioDir(MAJORAXIS);
		Plot1DNDFFunc(theApp.GetMATLABEngine(),pXYZFile);
	}
}


void CMFCD3D11TestView::OnPlot1dndffuncX()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		pXYZFile->SetCurNDFGenDir(XDIR);
		pXYZFile->SetCurGonioDir(MINORAXIS);
		Plot1DNDFFunc(theApp.GetMATLABEngine(),pXYZFile);
	}
}

bool CMFCD3D11TestView::Plot1DNDFFunc(CMatlabEng* matlabEng,CXYZFileIO* pXYZFile)
{
	NDFGENDIR ndfDir = pXYZFile->GetCurNDFGenDir();
	GONIOAXIS gonioAxis = pXYZFile->GetCurGonioDir();

	if((ndfDir==YDIR)&&(gonioAxis==MAJORAXIS))
	{
		pXYZFile->PrepareGonioData();
		return Plot1DNDFFunc_Y(theApp.GetMATLABEngine(),pXYZFile);
	}
	else if ((ndfDir==XDIR)&&(gonioAxis==MINORAXIS))
	{
		pXYZFile->PrepareGonioData();
		return Plot1DNDFFunc_X(theApp.GetMATLABEngine(),pXYZFile);
	}
	else
		return false;
}

void CMFCD3D11TestView::OnEditShow2dndfplot()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pCurXYZFile = pDoc->GetXYZFile();
	if(pCurXYZFile){
		UtilityString strXYZFileFullPath(pCurXYZFile->m_strXYZFileName);
		UtilityString strXYZFileName;
		strXYZFileFullPath.extractFNWithoutExt(strXYZFileName);
		strXYZFileName.ConcatenateStr("_2DNDF.bmp");
		m_dlg2DNDFVisual.SetBitmap(static_cast<LPCTSTR>(strXYZFileName.GetWCharStr()));
		m_dlg2DNDFVisual.ShowWindow(SW_SHOW);
	}	
	
}

void CMFCD3D11TestView::Prepare2DFitGGXSlice_Y(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, float a_x, float a_y, float b)
{
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	float fStep = 1.0f;//degree
	for (float fTheta = -90.0f; fTheta <=90.0f; fTheta=fTheta+fStep)//[-0.5pi,0.5pi]
	{
		if(fTheta == -90.0)
			arrAngles.Add(fTheta+0.5);
		else if(fTheta == 90.0)
			arrAngles.Add(fTheta-0.5);
		else
			arrAngles.Add(fTheta);

		double fThetaM = fTheta*DEGREE2RADIAN;
		double fPhiM = 0.5*D3DX_PI;
		if(fThetaM < 0)
		{
			fPhiM += D3DX_PI;
			fThetaM = -fThetaM;
		}

		double fNDFVal = CD3DUtilityFunction::EvalAnisotropicGGX(fThetaM,fPhiM,a_x,a_y,b);
		if(fNDFVal > 1.0)
			printf("ERROR");
		arrNDFVals.Add(fNDFVal);
	}
}

void CMFCD3D11TestView::Prepare2DFitBeckmannSlice_Y(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, float a_x, float a_y, float b)
{
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	float fStep = 1.0f;//degree
	for (float fTheta = -90.0f; fTheta <=90.0f; fTheta=fTheta+fStep)//[-0.5pi,0.5pi]
	{
		if(fTheta == -90.0)
			arrAngles.Add(fTheta+0.5);
		else if(fTheta == 90.0)
			arrAngles.Add(fTheta-0.5);
		else
			arrAngles.Add(fTheta);

		double fThetaM = fTheta*DEGREE2RADIAN;
		double fPhiM = 0.5*D3DX_PI;
		if(fThetaM < 0)
		{
			fPhiM += D3DX_PI;
			fThetaM = -fThetaM;
		}

		double fNDFVal = CD3DUtilityFunction::EvalAnisotropicBeckmann(fThetaM,fPhiM,a_x,a_y,b);
		if(fNDFVal > 1.0)
			printf("ERROR");
		arrNDFVals.Add(fNDFVal);
	}
}

void CMFCD3D11TestView::Prepare2DFitGGXSlice_X(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, float a_x, float a_y, float b)
{
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	//firstly fill angles nonuniformlly!
	float fStep = 5.0f;
	for(float fTheta = -90.0f; fTheta < -5.0f; fTheta+=fStep)
	{
		if(fTheta == -90.0)
			arrAngles.Add(fTheta+0.5);
		else
			arrAngles.Add(fTheta);
	}
	
	fStep = 0.1f;
	for(float fTheta = -5.0f; fTheta <= 5.0f; fTheta+=fStep)
		arrAngles.Add(fTheta);
	
	fStep = 5.0f;
	for(float fTheta = 10.0f; fTheta <=90.0f; fTheta+=fStep)
	{
		if(fTheta == 90.0)
			arrAngles.Add(fTheta-0.5);
		else
			arrAngles.Add(fTheta);
	}	
	//Compute NDF values
	for (int iIdx = 0; iIdx < arrAngles.GetSize(); iIdx++)
	{
		double fThetaM = arrAngles[iIdx]*DEGREE2RADIAN;
		double fPhiM = 0;
		if(fThetaM < 0)
		{
			fPhiM += D3DX_PI;
			fThetaM = -fThetaM;
		}

		double fNDFVal = CD3DUtilityFunction::EvalAnisotropicGGX(fThetaM,fPhiM,a_x,a_y,b);
		arrNDFVals.Add(fNDFVal);
	}

}

void CMFCD3D11TestView::Prepare2DFitBeckmannSlice_X(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, float a_x, float a_y, float b)
{
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	//firstly fill angles nonuniformlly!
	float fStep = 5.0f;
	for(float fTheta = -90.0f; fTheta < -5.0f; fTheta+=fStep)
	{
		if(fTheta == -90.0)
			arrAngles.Add(fTheta+0.5);
		else
			arrAngles.Add(fTheta);
	}

	fStep = 0.1f;
	for(float fTheta = -5.0f; fTheta <= 5.0f; fTheta+=fStep)
		arrAngles.Add(fTheta);

	fStep = 5.0f;
	for(float fTheta = 10.0f; fTheta <=90.0f; fTheta+=fStep)
	{
		if(fTheta == 90.0)
			arrAngles.Add(fTheta-0.5);
		else
			arrAngles.Add(fTheta);
	}	
	//Compute NDF values
	for (int iIdx = 0; iIdx < arrAngles.GetSize(); iIdx++)
	{
		double fThetaM = arrAngles[iIdx]*DEGREE2RADIAN;
		double fPhiM = 0;
		if(fThetaM < 0)
		{
			fPhiM += D3DX_PI;
			fThetaM = -fThetaM;
		}

		double fNDFVal = CD3DUtilityFunction::EvalAnisotropicBeckmann(fThetaM,fPhiM,a_x,a_y,b);
		arrNDFVals.Add(fNDFVal);
	}

}

void CMFCD3D11TestView::Prepare1DProfilDataSlice_X(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, CXYZFileIO* pXYZFile)
{
	int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();

	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	std::vector<double>& arrNDFCumulation = pXYZFile->Get2DNDFAccumArray();
	std::vector<CPoint> arr1DSlicePtsPos = m_dlg2DNDFVisual.m_wndBMP.Get1DSlicePoints_X();
	if(arr1DSlicePtsPos.size() > 0)
	{
		for (int iIdx = 0; iIdx < arr1DSlicePtsPos.size(); iIdx++)
		{
			int iXIdx = arr1DSlicePtsPos[iIdx].x;
			int iYIdx = arr1DSlicePtsPos[iIdx].y;
			//convert current 2d position to angle!
			float fThetaM = CD3DUtilityFunction::Convert2DPosToAngle(iXIdx,iYIdx,i2DNDFImgDim,i2DNDFImgDim,pXYZFile->GetCurNDFGenDir());
			arrAngles.Add(fThetaM);

			double value = 0;
			//int idx1 = (iYIdx-1)*i2DNDFImgDim+iXIdx;
			int idx1 = (iYIdx)*i2DNDFImgDim+iXIdx;
			if(m_bAvg1DNDF)
			{
				int idx2 = idx1 - i2DNDFImgDim;
				int idx3 = idx1 + i2DNDFImgDim;
				value = 0.5*arrNDFCumulation[idx1] + 0.25*arrNDFCumulation[idx2] + 0.25*arrNDFCumulation[idx3];
			}
			else
				value = arrNDFCumulation[idx1];
			arrNDFVals.Add(value);
		}
	}
}

void CMFCD3D11TestView::Prepare1DProfilDataSlice_Y(CGrowableArray<double>& arrAngles, CGrowableArray<double>& arrNDFVals, CXYZFileIO* pXYZFile)
{
	int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();

	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();

	std::vector<double>& arrNDFCumulation = pXYZFile->Get2DNDFAccumArray();
	std::vector<CPoint> arr1DSlicePtsPos = m_dlg2DNDFVisual.m_wndBMP.Get1DSlicePoints_Y();
	if(arr1DSlicePtsPos.size() > 0)
	{
		for (int iIdx = 0; iIdx < arr1DSlicePtsPos.size(); iIdx++)
		{
			int iXIdx = arr1DSlicePtsPos[iIdx].x;
			int iYIdx = arr1DSlicePtsPos[iIdx].y;
			//convert current 2d position to angle!
			float fThetaM = CD3DUtilityFunction::Convert2DPosToAngle(iXIdx,iYIdx,i2DNDFImgDim,i2DNDFImgDim,pXYZFile->GetCurNDFGenDir());
			arrAngles.Add(fThetaM);

			double value = 0;
			//int idx1 = iYIdx*i2DNDFImgDim+(iXIdx-1);
			int idx1 = iYIdx*i2DNDFImgDim+(iXIdx);
			if(m_bAvg1DNDF)
			{
				int idx2 = idx1 - 1;
				int idx3 = idx1 + 1;
				value = 0.5*arrNDFCumulation[idx1] + 0.25*arrNDFCumulation[idx2] + 0.25*arrNDFCumulation[idx3];
			}
			else
				value = arrNDFCumulation[idx1];
			arrNDFVals.Add(value);
		}	
	}
	else
	{
		//int iXIdx = i2DNDFImgDim/2;
		//for (int iYIdx = 0; iYIdx < i2DNDFImgDim; iYIdx++)
		//{
		//	//convert current 2d position to angle!
		//	float fThetaM = CD3DUtilityFunction::Convert2DPosToAngle(iXIdx,iYIdx,i2DNDFImgDim,i2DNDFImgDim,pXYZFile->GetCurNDFGenDir());
		//	arrAngles.Add(fThetaM);

		//	double value = 0;
		//	int idx1 = iYIdx*i2DNDFImgDim+(iXIdx-1);
		//	if(m_bAvg1DNDF)
		//	{
		//		int idx2 = idx1 - 1;
		//		int idx3 = idx1 + 1;
		//		value = 0.5*arrNDFCumulation[idx1] + 0.25*arrNDFCumulation[idx2] + 0.25*arrNDFCumulation[idx3];
		//	}
		//	else
		//		value = arrNDFCumulation[idx1];
		//	arrNDFVals.Add(value);
		//}
	}
	
}

bool CMFCD3D11TestView::Plot1DNDFFunc_X(CMatlabEng* matlabEng, CXYZFileIO* pXYZFile)
{
	if(!matlabEng)
		return false;
	
	CGrowableArray<double> arrAngles;
	CGrowableArray<double> arrNDFVals;
	Prepare1DProfilDataSlice_X(arrAngles,arrNDFVals,pXYZFile);
	
	//profilometer data
	int iNumProfilData = arrAngles.GetSize();
	mxArray *ProfilAngles = NULL;	
	ProfilAngles = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
	memcpy((void *)mxGetPr(ProfilAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumProfilData);

	mxArray *ProfilNDF = NULL;
	ProfilNDF = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
	memcpy((void *)mxGetPr(ProfilNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumProfilData);

	//Gonio Data
	std::vector<NDFItem>& arrGonioNDFData = pXYZFile->GetGonioNDFData();
	size_t iNumGonioNDF = arrGonioNDFData.size();
	mxArray *GonioAngles = NULL;
	GonioAngles = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
	std::vector<double> arrGonioTmp;
	for(size_t i = 0; i < iNumGonioNDF; i++)
		arrGonioTmp.push_back(arrGonioNDFData[i].AngleThetaM);
	memcpy((void*)mxGetPr(GonioAngles), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

	mxArray *GonioNDF = NULL;
	GonioNDF = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF; i++)
		arrGonioTmp.push_back(arrGonioNDFData[i].NDFVal);
	memcpy((void*)mxGetPr(GonioNDF), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

	//Gonio Data
	std::vector<NDFItem>& arrGonioNDFData_RIT = pXYZFile->GetGonioNDFData_RIT();
	size_t iNumGonioNDF_rit = arrGonioNDFData_RIT.size();
	mxArray *GonioAngles_rit = NULL;
	GonioAngles_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF_rit; i++)
		arrGonioTmp.push_back(arrGonioNDFData_RIT[i].AngleThetaM);
	memcpy((void*)mxGetPr(GonioAngles_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

	mxArray *GonioNDF_rit = NULL;
	GonioNDF_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF_rit; i++)
		arrGonioTmp.push_back(arrGonioNDFData_RIT[i].NDFVal);
	memcpy((void*)mxGetPr(GonioNDF_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

	//AGGX Fitted data
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();
	/*double a_x = 0.01106;
	double a_y = 0.2134;
	double b = 0.005856;	
	*/
	double a_x = m_fAlphaX_AGGX;
	double a_y = m_fAlphaY_AGGX;
	double b = m_fScalingFactor_AGGX;	

	Prepare2DFitGGXSlice_X(arrAngles,arrNDFVals,a_x,a_y,b);
	int iNumFitAGGXData = arrAngles.GetSize();
	mxArray *FitAGGXAngles = NULL;	
	FitAGGXAngles = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
	memcpy((void *)mxGetPr(FitAGGXAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitAGGXData);

	mxArray *FitAGGXNDF = NULL;
	FitAGGXNDF = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
	memcpy((void *)mxGetPr(FitAGGXNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitAGGXData);

	//Beckmann Fitted data
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();
	a_x = 0.0105;
	a_y = 0.2071;
	b = 0.00451;
	Prepare2DFitBeckmannSlice_X(arrAngles,arrNDFVals,a_x,a_y,b);
	int iNumFitBeckmannData = arrAngles.GetSize();
	mxArray *FitBeckmannAngles = NULL;	
	FitBeckmannAngles = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
	memcpy((void *)mxGetPr(FitBeckmannAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitBeckmannData);

	mxArray *FitBeckmannNDF = NULL;
	FitBeckmannNDF = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
	memcpy((void *)mxGetPr(FitBeckmannNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitBeckmannData);
	
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return false;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "NSize=%dx%d, \\sigma=%.2f", pXYZFile->GetNormalWndSize(),pXYZFile->GetNormalWndSize(),pXYZFile->GetGaussianSigma());
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
	}

	/*
	 * Place the variable T into the MATLAB workspace
	 */
	matlabEng->PutVariable("ProfilAngles", ProfilAngles);
	matlabEng->PutVariable("ProfilNDF", ProfilNDF);
	matlabEng->PutVariable("GonioAngles", GonioAngles);
	matlabEng->PutVariable("GonioNDF", GonioNDF);
	matlabEng->PutVariable("GonioAngles_rit", GonioAngles_rit);
	matlabEng->PutVariable("GonioNDF_rit", GonioNDF_rit);
	matlabEng->PutVariable("FitDataAngles", FitAGGXAngles);
	matlabEng->PutVariable("FitDataNDFs", FitAGGXNDF);
	matlabEng->PutVariable("FitDataAngles_B", FitBeckmannAngles);
	matlabEng->PutVariable("FitDataNDFs_B", FitBeckmannNDF);
	matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
	//matlabEng->EvalString("figure;");
	matlabEng->EvalString("clf;");
	matlabEng->EvalString("clear Plot1DNDF_Angle;");
	matlabEng->EvalString("Plot1DNDF_Angle(ProfilAngles,ProfilNDF,GonioAngles,GonioNDF,GonioAngles_rit,GonioNDF_rit,FitDataAngles,FitDataNDFs,FitDataAngles_B,FitDataNDFs_B,strDesc);");

	mxDestroyArray(ProfilAngles);
	mxDestroyArray(ProfilNDF);
	mxDestroyArray(GonioAngles);
	mxDestroyArray(GonioNDF);
	mxDestroyArray(GonioAngles_rit);
	mxDestroyArray(GonioNDF_rit);
	mxDestroyArray(FitAGGXAngles);
	mxDestroyArray(FitAGGXNDF);
	mxDestroyArray(FitBeckmannAngles);
	mxDestroyArray(FitBeckmannNDF);
	return true;
}

bool CMFCD3D11TestView::Plot1DNDFFunc_Y(CMatlabEng* matlabEng, CXYZFileIO* pXYZFile)
{
	if(!matlabEng)
		return false;
		
	CGrowableArray<double> arrAngles;
	CGrowableArray<double> arrNDFVals;
	Prepare1DProfilDataSlice_Y(arrAngles,arrNDFVals,pXYZFile);

	//profilometer data
	int iNumProfilData = arrAngles.GetSize();
	mxArray *ProfilAngles = NULL;	
	ProfilAngles = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
	memcpy((void *)mxGetPr(ProfilAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumProfilData);

	mxArray *ProfilNDF = NULL;
	ProfilNDF = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
	memcpy((void *)mxGetPr(ProfilNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumProfilData);

	//Gonio Data
	std::vector<NDFItem>& arrGonioNDFData = pXYZFile->GetGonioNDFData();
	size_t iNumGonioNDF = arrGonioNDFData.size();
	mxArray *GonioAngles = NULL;
	GonioAngles = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
	std::vector<double> arrGonioTmp;
	for(size_t i = 0; i < iNumGonioNDF; i++)
		arrGonioTmp.push_back(arrGonioNDFData[i].AngleThetaM);
	memcpy((void*)mxGetPr(GonioAngles), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

	mxArray *GonioNDF = NULL;
	GonioNDF = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF; i++)
		arrGonioTmp.push_back(arrGonioNDFData[i].NDFVal);
	memcpy((void*)mxGetPr(GonioNDF), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

	//Gonio Data
	std::vector<NDFItem>& arrGonioNDFData_RIT = pXYZFile->GetGonioNDFData_RIT();
	size_t iNumGonioNDF_rit = arrGonioNDFData_RIT.size();
	mxArray *GonioAngles_rit = NULL;
	GonioAngles_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF_rit; i++)
		arrGonioTmp.push_back(arrGonioNDFData_RIT[i].AngleThetaM);
	memcpy((void*)mxGetPr(GonioAngles_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

	mxArray *GonioNDF_rit = NULL;
	GonioNDF_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
	arrGonioTmp.clear();
	for(size_t i = 0; i < iNumGonioNDF_rit; i++)
		arrGonioTmp.push_back(arrGonioNDFData_RIT[i].NDFVal);
	memcpy((void*)mxGetPr(GonioNDF_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

	//AGGX Fitted data
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();
	//double a_x = 0.01106;
	//double a_x = 0.05506;
	//double a_y = 0.2134;
	double a_x = m_fAlphaX_AGGX;
	double a_y = m_fAlphaY_AGGX;
	double b = m_fScalingFactor_AGGX;
	
	//100x
	//double a_x = 0.01104;
	//double a_y = 0.2142;
	//double b = 0.005864;
	
	//400x
	//double a_x = 0.01088;
	//double a_y = 0.2152;
	//double b = 0.00583;
	
	//1000x
	//double a_x = 0.01049;
	//double a_y = 0.2158;
	//double b = 0.005709;
	
	Prepare2DFitGGXSlice_Y(arrAngles,arrNDFVals,a_x,a_y,b);
	int iNumFitAGGXData = arrAngles.GetSize();
	mxArray *FitAGGXAngles = NULL;	
	FitAGGXAngles = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
	memcpy((void *)mxGetPr(FitAGGXAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitAGGXData);

	mxArray *FitAGGXNDF = NULL;
	FitAGGXNDF = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
	memcpy((void *)mxGetPr(FitAGGXNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitAGGXData);

	//Beckmann Fitted data
	arrAngles.RemoveAll();
	arrNDFVals.RemoveAll();
	a_x = 0.0105;
	a_y = 0.2071;
	b = 0.00451;
	Prepare2DFitBeckmannSlice_Y(arrAngles,arrNDFVals,a_x,a_y,b);
	int iNumFitBeckmannData = arrAngles.GetSize();
	mxArray *FitBeckmannAngles = NULL;	
	FitBeckmannAngles = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
	memcpy((void *)mxGetPr(FitBeckmannAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitBeckmannData);

	mxArray *FitBeckmannNDF = NULL;
	FitBeckmannNDF = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
	memcpy((void *)mxGetPr(FitBeckmannNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitBeckmannData);
		
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return false;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "NSize=%dx%d, \\sigma=%.2f", pXYZFile->GetNormalWndSize(),pXYZFile->GetNormalWndSize(),pXYZFile->GetGaussianSigma());
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
	}

	/*
	 * Place the variable T into the MATLAB workspace
	 */
	matlabEng->PutVariable("ProfilAngles", ProfilAngles);
	matlabEng->PutVariable("ProfilNDF", ProfilNDF);
	matlabEng->PutVariable("GonioAngles", GonioAngles);
	matlabEng->PutVariable("GonioNDF", GonioNDF);
	matlabEng->PutVariable("GonioAngles_rit", GonioAngles_rit);
	matlabEng->PutVariable("GonioNDF_rit", GonioNDF_rit);
	matlabEng->PutVariable("FitDataAngles", FitAGGXAngles);
	matlabEng->PutVariable("FitDataNDFs", FitAGGXNDF);
	matlabEng->PutVariable("FitDataAngles_B", FitBeckmannAngles);
	matlabEng->PutVariable("FitDataNDFs_B", FitBeckmannNDF);
	matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
	//matlabEng->EvalString("figure;");
	matlabEng->EvalString("clf;");
	matlabEng->EvalString("clear Plot1DNDF_Angle;");
	matlabEng->EvalString("Plot1DNDF_Angle(ProfilAngles,ProfilNDF,GonioAngles,GonioNDF,GonioAngles_rit,GonioNDF_rit,FitDataAngles,FitDataNDFs,FitDataAngles_B,FitDataNDFs_B,strDesc);");

	mxDestroyArray(ProfilAngles);
	mxDestroyArray(ProfilNDF);
	mxDestroyArray(GonioAngles);
	mxDestroyArray(GonioNDF);
	mxDestroyArray(GonioAngles_rit);
	mxDestroyArray(GonioNDF_rit);
	mxDestroyArray(FitAGGXAngles);
	mxDestroyArray(FitAGGXNDF);
	mxDestroyArray(FitBeckmannAngles);
	mxDestroyArray(FitBeckmannNDF);
	return true;

}

void CMFCD3D11TestView::Prepare1DSliceHeightData(CGrowableArray<double>& arrPtPos, CGrowableArray<double>& arrHeightVals,std::vector<CPoint>& arrPts, float fCur1DLength, int iYDim, int iXDim)
{
	arrPtPos.RemoveAll();
	arrHeightVals.RemoveAll();

	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	for (int iPt = 0; iPt < arrPts.size(); iPt++)
	{
		int iY = arrPts[iPt].y;
		int iX = arrPts[iPt].x;
		int iIdx = iY*iXDim + iX;
		float fPos = 0;
		switch(m_iCurHeightBMPDir)
		{
		case Y_DIR:
			{
				fPos = iY;
				fPos = ((fPos+0.5)/iYDim)*fCur1DLength;
			}
			break;
		case X_DIR:
			{
				fPos = iX;
				fPos = ((fPos+0.5)/iXDim)*fCur1DLength;
			}
			break;
		}
		//add data to array
		arrPtPos.Add(fPos);
		arrHeightVals.Add(pDoc->GetXYZFile()->m_arrHeightMapData[iIdx]);
	}
	
}

bool CMFCD3D11TestView::Plot1DSliceHeight(CMatlabEng* matlabEng, std::vector<CPoint>& arrPts, float fCur1DLength,  int iYDim, int iXDim)
{
	if(!matlabEng)
		return false;
		
	CGrowableArray<double> arr1DPos;
	CGrowableArray<double> arrHeightVals;
	Prepare1DSliceHeightData(arr1DPos, arrHeightVals, arrPts, fCur1DLength, iYDim, iXDim);
	
	//profilometer data
	int iNumPts = arr1DPos.GetSize();
	mxArray *arr1DHeightSliceX = NULL;	
	arr1DHeightSliceX = mxCreateDoubleMatrix(1, iNumPts, mxREAL);
	memcpy((void *)mxGetPr(arr1DHeightSliceX), (void *)arr1DPos.GetData(), sizeof(double)*iNumPts);

	mxArray *arr1DHeightSliceY = NULL;
	arr1DHeightSliceY = mxCreateDoubleMatrix(1, iNumPts, mxREAL);
	memcpy((void *)mxGetPr(arr1DHeightSliceY), (void *)arrHeightVals.GetData(), sizeof(double)*iNumPts);

	/*
	 * Place the variable T into the MATLAB workspace
	 */
	matlabEng->PutVariable("arr1DHeightSliceX", arr1DHeightSliceX);
	matlabEng->PutVariable("arr1DHeightSliceY", arr1DHeightSliceY);
	matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
	//matlabEng->EvalString("figure;");
	matlabEng->EvalString("clf;");
	matlabEng->EvalString("clear Plot1DSliceHeight;");
	
	int iNumBatchPts = 480;
	int iNumFigs = iNumPts/iNumBatchPts;
	int iNumLastGroupPts = iNumPts%iNumBatchPts;
	bool bLastGroupDiff = false;
	if(iNumLastGroupPts > 0){
		iNumFigs++;
		bLastGroupDiff = true;
	}

	for(int iFig = 0; iFig < iNumFigs; iFig++) {

		matlabEng->EvalString("figure;");

		int iStartIdx = iFig * iNumBatchPts;
		int iEndIdx = iStartIdx + iNumBatchPts;
		if(iFig == iNumFigs-1 && bLastGroupDiff)
			iEndIdx = iStartIdx + iNumLastGroupPts;

		UtilityString strEval;
		if(m_iCurHeightBMPDir == Y_DIR)
			strEval.GenerateFormatSmallString("Plot1DSliceHeight(arr1DHeightSliceX,arr1DHeightSliceY, 'YDir',%d,%d);", iStartIdx+1, iEndIdx);
		else
			strEval.GenerateFormatSmallString("Plot1DSliceHeight(arr1DHeightSliceX,arr1DHeightSliceY, 'XDir',%d,%d);", iStartIdx+1, iEndIdx);

		matlabEng->EvalString(strEval.GetCharStr());
	}
	

	mxDestroyArray(arr1DHeightSliceX);
	mxDestroyArray(arr1DHeightSliceY);	
	return true;
}


void CMFCD3D11TestView::SetbAvg1DNDF(bool bAvg)
{
	if(bAvg == m_bAvg1DNDF)
		return;

	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		bool bOldAvg = m_bAvg1DNDF;
		m_bAvg1DNDF = bAvg;	 
		if(!Plot1DNDFFunc(theApp.GetMATLABEngine(),pXYZFile))
		{
			m_bAvg1DNDF = bOldAvg;
			return;
		}
	}
}

void CMFCD3D11TestView::OnEditSplitcoldir()
{
	// TODO: Add your command handler code here
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		int iNumRowPerPiece = 1000;
		bool bRt = pXYZFile->SplitXYZFilesColDir(iNumRowPerPiece);
		if(!bRt)
		{
			CString output(_T("Split files Failed!!!"));
			theApp.OutputString(output);
		}
	}
}


void CMFCD3D11TestView::OnEditComputendfmultiplefiles()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		int iMaxNumFiles = 10;
		TCHAR* strFilesNamesGroup = new TCHAR[MAX_PATH*iMaxNumFiles];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*MAX_PATH*iMaxNumFiles);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = 256;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle=50;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT;// | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			int iPos = strSelectedFiles.ReverseFind(_T('\\'));
			CString strFileNames = strSelectedFiles.Mid(iPos+1);
			CString strFileFolderPath = strSelectedFiles.TrimRight(strFileNames);
			strFileNames.TrimLeft();strFileNames.TrimRight();

			bool bFinished = false;
			//Get filtering method and sigma from GUI
			//
			NORMALESTIMATEMETHOD iCurNFMethod;
			int iKernelSize = 0;
			float fCurGaussSigma = 0.0f;
			//Query parameters for normal estimation
			queryXYZNormEstParamsFromUI(iCurNFMethod,iKernelSize,fCurGaussSigma);

			//TEMPORARIALLY FIXED!!!
			float fSampleWidth = 70;
			float fSampleHeight = 610;

			CString strOutput(_T("Start Generate NDF from multiple files:"));
		    theApp.OutputString(strOutput);
			//clear array
			m_arrNDFCumulation_LargeRegion.clear();
			int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();
			for (int j = 0; j < i2DNDFImgDim; j++)
				for (int i = 0; i < i2DNDFImgDim; i++)
					m_arrNDFCumulation_LargeRegion.push_back(0.0);	
			while (!bFinished)
			{
				CString strSingleFN;
				int iPos1 = strFileNames.Find(_T(' '));
				if(iPos1 >= 0)
					strSingleFN = strFileNames.Left(iPos1);
				else
				{
					strSingleFN = strFileNames;
					bFinished = true;
				}
				strFileNames.TrimLeft(strSingleFN);
				strFileNames.TrimLeft();
				CString strSingleFileFullPath = strFileFolderPath + strSingleFN;

				//theApp.OutputString(strSingleFileFullPath);
				//process each file!
				CXYZFileIO* pSingleXYZFile = new CXYZFileIO();
				//load files
				if(pSingleXYZFile->LoadFromFile(CT2A(strSingleFileFullPath),fSampleWidth,fSampleHeight) < 0)
					return;
				//temporarily change the members 
				pSingleXYZFile->m_iCurNormalEstiMethod = iCurNFMethod;
				pSingleXYZFile->m_fSigma = fCurGaussSigma;
				pSingleXYZFile->m_iNormalWndSize = iKernelSize;

				//estimate normals
				if(!pSingleXYZFile->EstimateNormalForEachPointNoAccumulation())
					return;
				//accumulation Normal
				ComputeNDFCumulationArray_Largeregion(pSingleXYZFile);
				
				//delete
				SAFE_DELETE(pSingleXYZFile);
				strOutput.Format(_T("%s processed!"), strSingleFileFullPath);
				theApp.OutputString(strOutput);
			}
			
			//normalization
			double fNormalizeFactor = 0;
			int iNumPixelsInCircle = ceil(i2DNDFImgDim*i2DNDFImgDim*(D3DX_PI/4.0));
			double fProjectSAPerPixel = (D3DX_PI/iNumPixelsInCircle);
			for (int j = 0; j < i2DNDFImgDim; j++)
				for(int i = 0; i < i2DNDFImgDim; i++)
				{
					double fVal = m_arrNDFCumulation_LargeRegion[j*i2DNDFImgDim+i];
					if( fVal > 0) //>0, otherwise no contribution
						fNormalizeFactor += fVal*fProjectSAPerPixel;
				}

				//normalization
				//and save matlab fitting data (.mfd)
				CString strMFDFullPath(strFileFolderPath);
				CString strTableFilePath(strFileFolderPath);
				strMFDFullPath.Append(_T("LargeRegion_2DNDF.mfd"));
				strTableFilePath.Append(_T("LargeRegion_2DNDF.txt"));


				FILE* fp = NULL;
				_tfopen_s(&fp, (LPCTSTR)strMFDFullPath,_T("w"));
				FILE* fp1 = NULL;
				_tfopen_s(&fp1, (LPCTSTR)strTableFilePath,_T("w"));
				fwprintf(fp1,_T("%d %d\n"),i2DNDFImgDim,i2DNDFImgDim);

				for (int j = 0; j < i2DNDFImgDim; j++)
					for(int i = 0; i < i2DNDFImgDim; i++)
					{
						int idx = j*i2DNDFImgDim+i;
						m_arrNDFCumulation_LargeRegion[idx] /= fNormalizeFactor;

						//save .mfd file
						if(m_arrNDFCumulation_LargeRegion[idx] > 0.1)
						{
							float fThetaM = 0.0f, fPhiM = 0.0f;
							CD3DUtilityFunction::Convert2DPosTo2Angles(i,j,i2DNDFImgDim,i2DNDFImgDim,fThetaM,fPhiM);
							fwprintf(fp,_T("%f %f %f\n"),fThetaM,fPhiM,m_arrNDFCumulation_LargeRegion[idx]);
							fwprintf(fp1,_T("%f "),m_arrNDFCumulation_LargeRegion[idx]);
						}
						else
							fwprintf(fp1,_T("0 "));
						//
						if(i == i2DNDFImgDim-1)
							fwprintf(fp1,_T("\n"));
					}
					fclose(fp);
					fclose(fp1);
				
					//save 2d ndf image
					HRESULT hr = S_OK;

					//Generate 2D normal histogram image
					CString strNHImgFullPath(strFileFolderPath);
					strNHImgFullPath.Append(_T("LargeRegion_2DNDF.bmp"));
					//SAVE BMP 
					ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();

					//hr = CD3DUtilityFunction::SaveNDFImage_Gray(pd3dDevice,strNHImgFullPath,m_i2DNDFImgDim,m_i2DNDFImgDim,m_arrNDFCumulation);
					hr = CD3DUtilityFunction::SaveNDFImage(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);
					//SAVE DDS file
					strNHImgFullPath.TrimRight(_T(".bmp"));
					strNHImgFullPath.Append(_T(".dds"));
					hr = CD3DUtilityFunction::SaveNDFFloatImageData(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);

					if(hr == S_OK) 
					{
						CString strTmp;
						strTmp.Format(_T("%s Generated!"), strNHImgFullPath);
						theApp.OutputString(strTmp);
					}

		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
	
}

void CMFCD3D11TestView::ComputeNDFCumulationArray_Largeregion(CXYZFileIO* pSmallXYZFile)
{
	if(!pSmallXYZFile || pSmallXYZFile->m_arrNormalAreaWeighted.size() == 0)
		return;
	int iDim = pSmallXYZFile->GetCur2DNDFImgDim();
	if(m_arrNDFCumulation_LargeRegion.size() == 0)
	{
		for (int j = 0; j < iDim; j++)
			for (int i = 0; i < iDim; i++)
				m_arrNDFCumulation_LargeRegion.push_back(0.0);	
	}
	//loop all normals
	for (int i = 0; i < pSmallXYZFile->m_arrNormalAreaWeighted.size(); i++)
	{
		D3DXVECTOR3 norm = pSmallXYZFile->m_arrNormalAreaWeighted[i].Normal;
		norm.x = norm.x/2.0f + 0.5f; //(-1,1) --> (0,1); 
		norm.y = norm.y/2.0f + 0.5f;
		int iPosX = (int)(floorf(norm.x * iDim));
		int iPosY = (int)(floorf(norm.y * iDim));
		if(iPosX == iDim) iPosX--;
		if(iPosY == iDim) iPosY--;
		unsigned int idx = iPosY*iDim + iPosX;
		m_arrNDFCumulation_LargeRegion[idx] += 1.0;
	}	
}


void CMFCD3D11TestView::OnEditSubstractfrombigndf()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		CString strNDFFloatDataFile(pXYZFile->GetStrXYZFilePathName());
		int iPos = strNDFFloatDataFile.ReverseFind('.');
		CString strXYZFileName = strNDFFloatDataFile.Mid(iPos);
		strNDFFloatDataFile.TrimRight(strXYZFileName);	
		strNDFFloatDataFile.Append(_T("_2DNDF.dds"));

		CString strLargeNDFFloatDataFile(pXYZFile->GetStrXYZFilePathName());
		iPos = strLargeNDFFloatDataFile.ReverseFind('\\');
		strXYZFileName = strLargeNDFFloatDataFile.Mid(iPos+1);
		strLargeNDFFloatDataFile.TrimRight(strXYZFileName);	
		strLargeNDFFloatDataFile.Append(_T("Large_2DNDF.dds"));

		CString strDiffNDFFloatDataFile(pXYZFile->GetStrXYZFilePathName());
		iPos = strDiffNDFFloatDataFile.ReverseFind('.');
		strXYZFileName = strDiffNDFFloatDataFile.Mid(iPos);
		strDiffNDFFloatDataFile.TrimRight(strXYZFileName);	
		strDiffNDFFloatDataFile.Append(_T("_Diff.bmp"));

		ID3D11Device* pDevice = AfxDXGlobal()->Device();
		CD3DUtilityFunction::GenDiffOfTowTextures(pDevice,(LPCTSTR)strNDFFloatDataFile, (LPCTSTR)strLargeNDFFloatDataFile,(LPCTSTR)strDiffNDFFloatDataFile, DXGI_FORMAT_R32_FLOAT);
	}
}


void CMFCD3D11TestView::OnEditSplitrowdir()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		int iNumColPerPiece = 1054;
		bool bRt = pXYZFile->SplitXYZFilesRowDir(iNumColPerPiece);
		if(!bRt)
		{
			CString output(_T("Split files Failed!!!"));
			theApp.OutputString(output);
		}
	}
}


void CMFCD3D11TestView::OnEditComputendfmultiplefilesrowdir()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		int iMaxNumFiles = 10;
		TCHAR* strFilesNamesGroup = new TCHAR[MAX_PATH*iMaxNumFiles];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*MAX_PATH*iMaxNumFiles);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = 256;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle=50;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT;// | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			int iPos = strSelectedFiles.ReverseFind(_T('\\'));
			CString strFileNames = strSelectedFiles.Mid(iPos+1);
			CString strFileFolderPath = strSelectedFiles.TrimRight(strFileNames);
			strFileNames.TrimLeft();strFileNames.TrimRight();

			bool bFinished = false;
			//Get filtering method and sigma from GUI
			//
			NORMALESTIMATEMETHOD iCurNFMethod;
			int iKernelSize = 0;
			float fCurGaussSigma = 0.0f;

			queryXYZNormEstParamsFromUI(iCurNFMethod,iKernelSize,fCurGaussSigma);
			//temporarially fixed!!!
			float fSampleWidth = 810;
			float fSampleHeight = 55;

			CString strOutput(_T("Start Generate NDF from multiple files:"));
			theApp.OutputString(strOutput);
			//clear array
			m_arrNDFCumulation_LargeRegion.clear();
			int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();
			for (int j = 0; j < i2DNDFImgDim; j++)
				for (int i = 0; i < i2DNDFImgDim; i++)
					m_arrNDFCumulation_LargeRegion.push_back(0.0);	
			while (!bFinished)
			{
				CString strSingleFN;
				int iPos1 = strFileNames.Find(_T(' '));
				if(iPos1 >= 0)
					strSingleFN = strFileNames.Left(iPos1);
				else
				{
					strSingleFN = strFileNames;
					bFinished = true;
				}
				strFileNames.TrimLeft(strSingleFN);
				strFileNames.TrimLeft();
				CString strSingleFileFullPath = strFileFolderPath + strSingleFN;

				//theApp.OutputString(strSingleFileFullPath);
				//process each file!
				CXYZFileIO* pSingleXYZFile = new CXYZFileIO();
				//load files
				if(pSingleXYZFile->LoadFromFile(CT2A(strSingleFileFullPath),fSampleWidth,fSampleHeight) < 0)
					return;
				//temporarily change the members 
				pSingleXYZFile->m_iCurNormalEstiMethod = iCurNFMethod;
				pSingleXYZFile->m_fSigma = fCurGaussSigma;

				//estimate normals
				if(!pSingleXYZFile->EstimateNormalForEachPointNoAccumulation())
					return;
				//accumulation Normal
				ComputeNDFCumulationArray_Largeregion(pSingleXYZFile);

				//delete
				SAFE_DELETE(pSingleXYZFile);
				strOutput.Format(_T("%s processed!"), strSingleFileFullPath);
				theApp.OutputString(strOutput);
			}

			//normalization
			double fNormalizeFactor = 0;
			int iNumPixelsInCircle = (int)(ceil(i2DNDFImgDim*i2DNDFImgDim*(D3DX_PI/4.0)));
			double fProjectSAPerPixel = (D3DX_PI/iNumPixelsInCircle);
			for (int j = 0; j < i2DNDFImgDim; j++)
				for(int i = 0; i < i2DNDFImgDim; i++)
				{
					double fVal = m_arrNDFCumulation_LargeRegion[j*i2DNDFImgDim+i];
					if( fVal > 0) //>0, otherwise no contribution
						fNormalizeFactor += fVal*fProjectSAPerPixel;
				}

				//normalization
				//and save matlab fitting data (.mfd)
				CString strMFDFullPath(strFileFolderPath);
				CString strTableFilePath(strFileFolderPath);
				strMFDFullPath.Append(_T("LargeRegion_2DNDF.mfd"));
				strTableFilePath.Append(_T("LargeRegion_2DNDF.txt"));


				FILE* fp = NULL;
				_tfopen_s(&fp,(LPCTSTR)strMFDFullPath,_T("w"));
				FILE* fp1 = NULL;
				_tfopen_s(&fp1,(LPCTSTR)strTableFilePath,_T("w"));
				fwprintf(fp1,_T("%d %d\n"),i2DNDFImgDim,i2DNDFImgDim);

				for (int j = 0; j < i2DNDFImgDim; j++)
					for(int i = 0; i < i2DNDFImgDim; i++)
					{
						int idx = j*i2DNDFImgDim+i;
						m_arrNDFCumulation_LargeRegion[idx] /= fNormalizeFactor;

						//save .mfd file
						if(m_arrNDFCumulation_LargeRegion[idx] > 0.1)
						{
							float fThetaM = 0.0f, fPhiM = 0.0f;
							CD3DUtilityFunction::Convert2DPosTo2Angles(i,j,i2DNDFImgDim,i2DNDFImgDim,fThetaM,fPhiM);
							fwprintf(fp,_T("%f %f %f\n"),fThetaM,fPhiM,m_arrNDFCumulation_LargeRegion[idx]);
							fwprintf(fp1,_T("%f "),m_arrNDFCumulation_LargeRegion[idx]);
						}
						else
							fwprintf(fp1,_T("0 "));
						//
						if(i == i2DNDFImgDim-1)
							fwprintf(fp1,_T("\n"));
					}
					fclose(fp);
					fclose(fp1);

					//save 2d ndf image
					HRESULT hr = S_OK;

					//Generate 2D normal histogram image
					CString strNHImgFullPath(strFileFolderPath);
					strNHImgFullPath.Append(_T("LargeRegion_2DNDF.bmp"));
					//SAVE BMP 
					ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();

					//hr = CD3DUtilityFunction::SaveNDFImage_Gray(pd3dDevice,strNHImgFullPath,m_i2DNDFImgDim,m_i2DNDFImgDim,m_arrNDFCumulation);
					hr = CD3DUtilityFunction::SaveNDFImage(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);
					//SAVE DDS file
					strNHImgFullPath.TrimRight(_T(".bmp"));
					strNHImgFullPath.Append(_T(".dds"));
					hr = CD3DUtilityFunction::SaveNDFFloatImageData(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);

					if(hr == S_OK) 
					{
						CString strTmp;
						strTmp.Format(_T("%s Generated!"), strNHImgFullPath);
						theApp.OutputString(strTmp);
					}

		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}

}


void CMFCD3D11TestView::OnEditPlot1dndffuncYLargeregion()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		/************************************************************************************************************/
		//
		/************************************************************************************************************/
		CString strLargeNDFFloatDataFile(pXYZFile->GetStrXYZFilePathName());
		int iPos = strLargeNDFFloatDataFile.ReverseFind('\\');
		CString strXYZFileName = strLargeNDFFloatDataFile.Mid(iPos+1);
		strLargeNDFFloatDataFile.TrimRight(strXYZFileName);	
		strLargeNDFFloatDataFile.Append(_T("LargeRegion_2DNDF.dds"));

		//prepare the ndf data from .dds
		//Load Second Texture
		ID3D11Texture2D* pTexLargeNDF = NULL;
		D3DX11_IMAGE_LOAD_INFO img_load_info1;
		img_load_info1.Width = D3DX11_DEFAULT;
		img_load_info1.Height = D3DX11_DEFAULT;
		img_load_info1.Depth = D3DX11_DEFAULT;
		img_load_info1.FirstMipLevel = D3DX11_DEFAULT;
		img_load_info1.MipLevels = 1;
		img_load_info1.Usage = D3D11_USAGE_STAGING;
		img_load_info1.BindFlags = 0;
		img_load_info1.CpuAccessFlags = D3D11_CPU_ACCESS_READ;
		img_load_info1.MiscFlags = 0;
		img_load_info1.Format = DXGI_FORMAT_R32_FLOAT;    
		img_load_info1.Filter = D3DX11_DEFAULT;
		img_load_info1.MipFilter = D3DX11_DEFAULT;
		img_load_info1.pSrcInfo = NULL;

		ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();
		HRESULT hr = S_OK;
		D3DX11CreateTextureFromFile( pd3dDevice, strLargeNDFFloatDataFile, &img_load_info1, NULL, 
			(ID3D11Resource**)(&pTexLargeNDF), &hr );
		if(hr!=S_OK)
			return;

		//save texture information.
		D3D11_TEXTURE2D_DESC TexDesc1;
		pTexLargeNDF->GetDesc(&TexDesc1);
		int iWidth = TexDesc1.Width;
		int iHeight = TexDesc1.Height;

		//lock two textures and compute the differences!
		ID3D11DeviceContext* pd3dImmediateContext;
		pd3dDevice->GetImmediateContext(&pd3dImmediateContext);

		float* arrNDFData = new float[iWidth*iHeight];
		// map for reading
		D3D11_MAPPED_SUBRESOURCE MappedResourceLargeNDF; 
		V(pd3dImmediateContext->Map(pTexLargeNDF, 0, D3D11_MAP_READ, 0, &MappedResourceLargeNDF));

		float* pLargeNDFPixel = (float*)(MappedResourceLargeNDF.pData);
		for (int j = 0; j < iHeight; j++)
			for(int i = 0; i < iWidth; i++)
			{
				unsigned int idx = j*iWidth + i;
				unsigned int idx1 = j*(MappedResourceLargeNDF.RowPitch/sizeof(float)) + i;

				arrNDFData[idx] = *(pLargeNDFPixel+idx1);
			}
			//unmap
			pd3dImmediateContext->Unmap(pTexLargeNDF,0);

			//load the Y slice data
			pXYZFile->SetCurNDFGenDir(YDIR);
			CGrowableArray<double> arrAngles;
			CGrowableArray<double> arrNDFVals;
			std::vector<CPoint> arr1DSlicePtsPos = m_dlg2DNDFVisual.m_wndBMP.Get1DSlicePoints_Y();
			if(arr1DSlicePtsPos.size() > 0)
			{
				for (int iIdx = 0; iIdx < arr1DSlicePtsPos.size(); iIdx++)
				{
					int iXIdx = arr1DSlicePtsPos[iIdx].x;
					int iYIdx = arr1DSlicePtsPos[iIdx].y;
					//convert current 2d position to angle!
					float fThetaM = CD3DUtilityFunction::Convert2DPosToAngle(iXIdx,iYIdx,iWidth,iHeight,pXYZFile->GetCurNDFGenDir());
					arrAngles.Add(fThetaM);

					double value = 0;
					//int idx1 = iYIdx*i2DNDFImgDim+(iXIdx-1);
					int idx1 = iYIdx*iWidth+(iXIdx);
					if(m_bAvg1DNDF)
					{
						int idx2 = idx1 - 1;
						int idx3 = idx1 + 1;
						value = 0.5*arrNDFData[idx1] + 0.25*arrNDFData[idx2] + 0.25*arrNDFData[idx3];
					}
					else
						value = arrNDFData[idx1];
					arrNDFVals.Add(value);
				}	
			}

			SAFE_DELETE_ARRAY(arrNDFData);
			/************************************************************************************************************/
			//
			/************************************************************************************************************/
			//prepare gonio data
			pXYZFile->SetCurGonioDir(MAJORAXIS);
			pXYZFile->PrepareGonioData();
			/************************************************************************************************************/
			//
			/************************************************************************************************************/
			//plot data
			CMatlabEng* matlabEng = theApp.GetMATLABEngine();
			if(!matlabEng)
				return;

			//profilometer data
			int iNumProfilData = arrAngles.GetSize();
			mxArray *ProfilAngles = NULL;	
			ProfilAngles = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
			memcpy((void *)mxGetPr(ProfilAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumProfilData);

			mxArray *ProfilNDF = NULL;
			ProfilNDF = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
			memcpy((void *)mxGetPr(ProfilNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumProfilData);

			//Gonio Data
			std::vector<NDFItem>& arrGonioNDFData = pXYZFile->GetGonioNDFData();
			size_t iNumGonioNDF = arrGonioNDFData.size();
			mxArray *GonioAngles = NULL;
			GonioAngles = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
			std::vector<double> arrGonioTmp;
			for(size_t i = 0; i < iNumGonioNDF; i++)
				arrGonioTmp.push_back(arrGonioNDFData[i].AngleThetaM);
			memcpy((void*)mxGetPr(GonioAngles), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

			mxArray *GonioNDF = NULL;
			GonioNDF = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF; i++)
				arrGonioTmp.push_back(arrGonioNDFData[i].NDFVal);
			memcpy((void*)mxGetPr(GonioNDF), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

			//Gonio Data
			std::vector<NDFItem>& arrGonioNDFData_RIT = pXYZFile->GetGonioNDFData_RIT();
			size_t iNumGonioNDF_rit = arrGonioNDFData_RIT.size();
			mxArray *GonioAngles_rit = NULL;
			GonioAngles_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF_rit; i++)
				arrGonioTmp.push_back(arrGonioNDFData_RIT[i].AngleThetaM);
			memcpy((void*)mxGetPr(GonioAngles_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

			mxArray *GonioNDF_rit = NULL;
			GonioNDF_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF_rit; i++)
				arrGonioTmp.push_back(arrGonioNDFData_RIT[i].NDFVal);
			memcpy((void*)mxGetPr(GonioNDF_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

			//AGGX Fitted data
			arrAngles.RemoveAll();
			arrNDFVals.RemoveAll();
			//double a_x = 0.01106;
			//double a_y = 0.2134;
			//double b = 0.005856;

			//100x
			/*double a_x = 0.01104;
			double a_y = 0.2142;
			double b = 0.005864;*/

			//400x
			//double a_x = 0.01088;
			//double a_y = 0.2152;
			//double b = 0.00583;

			//1000x
			//double a_x = 0.01049;
			//double a_y = 0.2158;
			//double b = 0.005709;

			double a_x = m_fAlphaX_AGGX;
			double a_y = m_fAlphaY_AGGX;
			double b = m_fScalingFactor_AGGX;
			
			Prepare2DFitGGXSlice_Y(arrAngles,arrNDFVals,a_x,a_y,b);
			int iNumFitAGGXData = arrAngles.GetSize();
			mxArray *FitAGGXAngles = NULL;	
			FitAGGXAngles = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
			memcpy((void *)mxGetPr(FitAGGXAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitAGGXData);

			mxArray *FitAGGXNDF = NULL;
			FitAGGXNDF = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
			memcpy((void *)mxGetPr(FitAGGXNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitAGGXData);

			//Beckmann Fitted data
			arrAngles.RemoveAll();
			arrNDFVals.RemoveAll();
			a_x = 0.0105;
			a_y = 0.2071;
			b = 0.00451;
			Prepare2DFitBeckmannSlice_Y(arrAngles,arrNDFVals,a_x,a_y,b);
			int iNumFitBeckmannData = arrAngles.GetSize();
			mxArray *FitBeckmannAngles = NULL;	
			FitBeckmannAngles = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
			memcpy((void *)mxGetPr(FitBeckmannAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitBeckmannData);

			mxArray *FitBeckmannNDF = NULL;
			FitBeckmannNDF = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
			memcpy((void *)mxGetPr(FitBeckmannNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitBeckmannData);

			//prepare the string to show the neighbor size and sigma value
			CMFCD3D11TestDoc* pDoc = GetDocument();
			ASSERT_VALID(pDoc);
			if (!pDoc)
				return;

			char strTmp[MAX_PATH];
			ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
			sprintf_s( strTmp, "NSize=%dx%d, \\sigma=%.2f", pXYZFile->GetNormalWndSize(),pXYZFile->GetNormalWndSize(),pXYZFile->GetGaussianSigma());
			mxArray* strDescMat = mxCreateString(strTmp);
			matlabEng->PutVariable("strDesc", strDescMat);
			/*
			* Place the variable T into the MATLAB workspace
			*/
			matlabEng->PutVariable("ProfilAngles", ProfilAngles);
			matlabEng->PutVariable("ProfilNDF", ProfilNDF);
			matlabEng->PutVariable("GonioAngles", GonioAngles);
			matlabEng->PutVariable("GonioNDF", GonioNDF);
			matlabEng->PutVariable("GonioAngles_rit", GonioAngles_rit);
			matlabEng->PutVariable("GonioNDF_rit", GonioNDF_rit);
			matlabEng->PutVariable("FitDataAngles", FitAGGXAngles);
			matlabEng->PutVariable("FitDataNDFs", FitAGGXNDF);
			matlabEng->PutVariable("FitDataAngles_B", FitBeckmannAngles);
			matlabEng->PutVariable("FitDataNDFs_B", FitBeckmannNDF);
			matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
			//matlabEng->EvalString("figure;");
			matlabEng->EvalString("clf;");
			matlabEng->EvalString("clear Plot1DNDF_Angle;");
			matlabEng->EvalString("Plot1DNDF_Angle(ProfilAngles,ProfilNDF,GonioAngles,GonioNDF,GonioAngles_rit,GonioNDF_rit,FitDataAngles,FitDataNDFs,FitDataAngles_B,FitDataNDFs_B,strDesc);");

			mxDestroyArray(ProfilAngles);
			mxDestroyArray(ProfilNDF);
			mxDestroyArray(GonioAngles);
			mxDestroyArray(GonioNDF);
			mxDestroyArray(GonioAngles_rit);
			mxDestroyArray(GonioNDF_rit);
			mxDestroyArray(FitAGGXAngles);
			mxDestroyArray(FitAGGXNDF);
			mxDestroyArray(FitBeckmannAngles);
			mxDestroyArray(FitBeckmannNDF);
			//release resources
			SAFE_RELEASE(pd3dImmediateContext);
			SAFE_RELEASE(pTexLargeNDF);

	}
}


void CMFCD3D11TestView::OnEditPlot1dndffuncXLargeregion()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		/************************************************************************************************************/
		//
		/************************************************************************************************************/
		CString strLargeNDFFloatDataFile(pXYZFile->GetStrXYZFilePathName());
		int iPos = strLargeNDFFloatDataFile.ReverseFind('\\');
		CString strXYZFileName = strLargeNDFFloatDataFile.Mid(iPos+1);
		strLargeNDFFloatDataFile.TrimRight(strXYZFileName);	
		strLargeNDFFloatDataFile.Append(_T("LargeRegion_2DNDF.dds"));

		//prepare the ndf data from .dds
		//Load Second Texture
		ID3D11Texture2D* pTexLargeNDF = NULL;
		D3DX11_IMAGE_LOAD_INFO img_load_info1;
		img_load_info1.Width = D3DX11_DEFAULT;
		img_load_info1.Height = D3DX11_DEFAULT;
		img_load_info1.Depth = D3DX11_DEFAULT;
		img_load_info1.FirstMipLevel = D3DX11_DEFAULT;
		img_load_info1.MipLevels = 1;
		img_load_info1.Usage = D3D11_USAGE_STAGING;
		img_load_info1.BindFlags = 0;
		img_load_info1.CpuAccessFlags = D3D11_CPU_ACCESS_READ;
		img_load_info1.MiscFlags = 0;
		img_load_info1.Format = DXGI_FORMAT_R32_FLOAT;    
		img_load_info1.Filter = D3DX11_DEFAULT;
		img_load_info1.MipFilter = D3DX11_DEFAULT;
		img_load_info1.pSrcInfo = NULL;

		ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();
		HRESULT hr = S_OK;
		D3DX11CreateTextureFromFile( pd3dDevice, strLargeNDFFloatDataFile, &img_load_info1, NULL, 
			(ID3D11Resource**)(&pTexLargeNDF), &hr );
		if(hr!=S_OK)
			return;

		//save texture information.
		D3D11_TEXTURE2D_DESC TexDesc1;
		pTexLargeNDF->GetDesc(&TexDesc1);
		int iWidth = TexDesc1.Width;
		int iHeight = TexDesc1.Height;

		//lock two textures and compute the differences!
		ID3D11DeviceContext* pd3dImmediateContext;
		pd3dDevice->GetImmediateContext(&pd3dImmediateContext);

		float* arrNDFData = new float[iWidth*iHeight];
		// map for reading
		D3D11_MAPPED_SUBRESOURCE MappedResourceLargeNDF; 
		V(pd3dImmediateContext->Map(pTexLargeNDF, 0, D3D11_MAP_READ, 0, &MappedResourceLargeNDF));

		float* pLargeNDFPixel = (float*)(MappedResourceLargeNDF.pData);
		for (int j = 0; j < iHeight; j++)
			for(int i = 0; i < iWidth; i++)
			{
				unsigned int idx = j*iWidth + i;
				unsigned int idx1 = j*(MappedResourceLargeNDF.RowPitch/sizeof(float)) + i;

				arrNDFData[idx] = *(pLargeNDFPixel+idx1);
			}
			//unmap
			pd3dImmediateContext->Unmap(pTexLargeNDF,0);

			//load the Y slice data
			pXYZFile->SetCurNDFGenDir(XDIR);
			CGrowableArray<double> arrAngles;
			CGrowableArray<double> arrNDFVals;
			std::vector<CPoint> arr1DSlicePtsPos = m_dlg2DNDFVisual.m_wndBMP.Get1DSlicePoints_X();
			if(arr1DSlicePtsPos.size() > 0)
			{
				for (int iIdx = 0; iIdx < arr1DSlicePtsPos.size(); iIdx++)
				{
					int iXIdx = arr1DSlicePtsPos[iIdx].x;
					int iYIdx = arr1DSlicePtsPos[iIdx].y;
					//convert current 2d position to angle!
					float fThetaM = CD3DUtilityFunction::Convert2DPosToAngle(iXIdx,iYIdx,iWidth,iHeight,pXYZFile->GetCurNDFGenDir());
					arrAngles.Add(fThetaM);

					double value = 0;
					//int idx1 = iYIdx*i2DNDFImgDim+(iXIdx-1);
					int idx1 = iYIdx*iWidth+(iXIdx);
					if(m_bAvg1DNDF)
					{
						int idx2 = idx1 - 1;
						int idx3 = idx1 + 1;
						value = 0.5*arrNDFData[idx1] + 0.25*arrNDFData[idx2] + 0.25*arrNDFData[idx3];
					}
					else
						value = arrNDFData[idx1];
					arrNDFVals.Add(value);
				}	
			}

			SAFE_DELETE_ARRAY(arrNDFData);
			/************************************************************************************************************/
			//
			/************************************************************************************************************/
			//prepare gonio data
			pXYZFile->SetCurGonioDir(MINORAXIS);
			pXYZFile->PrepareGonioData();
			/************************************************************************************************************/
			//
			/************************************************************************************************************/
			//plot data
			CMatlabEng* matlabEng = theApp.GetMATLABEngine();
			if(!matlabEng)
				return;

			//profilometer data
			int iNumProfilData = arrAngles.GetSize();
			mxArray *ProfilAngles = NULL;	
			ProfilAngles = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
			memcpy((void *)mxGetPr(ProfilAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumProfilData);

			mxArray *ProfilNDF = NULL;
			ProfilNDF = mxCreateDoubleMatrix(1, iNumProfilData, mxREAL);
			memcpy((void *)mxGetPr(ProfilNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumProfilData);

			//Gonio Data
			std::vector<NDFItem>& arrGonioNDFData = pXYZFile->GetGonioNDFData();
			size_t iNumGonioNDF = arrGonioNDFData.size();
			mxArray *GonioAngles = NULL;
			GonioAngles = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
			std::vector<double> arrGonioTmp;
			for(size_t i = 0; i < iNumGonioNDF; i++)
				arrGonioTmp.push_back(arrGonioNDFData[i].AngleThetaM);
			memcpy((void*)mxGetPr(GonioAngles), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

			mxArray *GonioNDF = NULL;
			GonioNDF = mxCreateDoubleMatrix(1, iNumGonioNDF, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF; i++)
				arrGonioTmp.push_back(arrGonioNDFData[i].NDFVal);
			memcpy((void*)mxGetPr(GonioNDF), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF);

			//Gonio Data
			std::vector<NDFItem>& arrGonioNDFData_RIT = pXYZFile->GetGonioNDFData_RIT();
			size_t iNumGonioNDF_rit = arrGonioNDFData_RIT.size();
			mxArray *GonioAngles_rit = NULL;
			GonioAngles_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF_rit; i++)
				arrGonioTmp.push_back(arrGonioNDFData_RIT[i].AngleThetaM);
			memcpy((void*)mxGetPr(GonioAngles_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

			mxArray *GonioNDF_rit = NULL;
			GonioNDF_rit = mxCreateDoubleMatrix(1, iNumGonioNDF_rit, mxREAL);
			arrGonioTmp.clear();
			for(size_t i = 0; i < iNumGonioNDF_rit; i++)
				arrGonioTmp.push_back(arrGonioNDFData_RIT[i].NDFVal);
			memcpy((void*)mxGetPr(GonioNDF_rit), (void*)arrGonioTmp.data(), sizeof(double)*iNumGonioNDF_rit);

			//AGGX Fitted data
			arrAngles.RemoveAll();
			arrNDFVals.RemoveAll();
			//double a_x = 0.01106;
			//double a_y = 0.2134;
			//double b = 0.005856;

			//100x
		/*	double a_x = 0.01104;
			double a_y = 0.2142;
			double b = 0.005864;*/

			//400x
			//double a_x = 0.01088;
			//double a_y = 0.2152;
			//double b = 0.00583;

			//1000x
			//double a_x = 0.01049;
			//double a_y = 0.2158;
			//double b = 0.005709;

			double a_x = m_fAlphaX_AGGX;
			double a_y = m_fAlphaY_AGGX;
			double b = m_fScalingFactor_AGGX;

			Prepare2DFitGGXSlice_X(arrAngles,arrNDFVals,a_x,a_y,b);
			int iNumFitAGGXData = arrAngles.GetSize();
			mxArray *FitAGGXAngles = NULL;	
			FitAGGXAngles = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
			memcpy((void *)mxGetPr(FitAGGXAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitAGGXData);

			mxArray *FitAGGXNDF = NULL;
			FitAGGXNDF = mxCreateDoubleMatrix(1, iNumFitAGGXData, mxREAL);
			memcpy((void *)mxGetPr(FitAGGXNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitAGGXData);

			//Beckmann Fitted data
			arrAngles.RemoveAll();
			arrNDFVals.RemoveAll();
			a_x = 0.0105;
			a_y = 0.2071;
			b = 0.00451;
			Prepare2DFitBeckmannSlice_X(arrAngles,arrNDFVals,a_x,a_y,b);
			int iNumFitBeckmannData = arrAngles.GetSize();
			mxArray *FitBeckmannAngles = NULL;	
			FitBeckmannAngles = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
			memcpy((void *)mxGetPr(FitBeckmannAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumFitBeckmannData);

			mxArray *FitBeckmannNDF = NULL;
			FitBeckmannNDF = mxCreateDoubleMatrix(1, iNumFitBeckmannData, mxREAL);
			memcpy((void *)mxGetPr(FitBeckmannNDF), (void *)arrNDFVals.GetData(), sizeof(double)*iNumFitBeckmannData);

			//prepare the string to show the neighbor size and sigma value
			CMFCD3D11TestDoc* pDoc = GetDocument();
			ASSERT_VALID(pDoc);
			if (!pDoc)
				return;

			char strTmp[MAX_PATH];
			ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
			sprintf_s( strTmp, "NSize=%dx%d, \\sigma=%.2f", pXYZFile->GetNormalWndSize(),pXYZFile->GetNormalWndSize(),pXYZFile->GetGaussianSigma());
			mxArray* strDescMat = mxCreateString(strTmp);
			matlabEng->PutVariable("strDesc", strDescMat);
			/*
			* Place the variable T into the MATLAB workspace
			*/
			matlabEng->PutVariable("ProfilAngles", ProfilAngles);
			matlabEng->PutVariable("ProfilNDF", ProfilNDF);
			matlabEng->PutVariable("GonioAngles", GonioAngles);
			matlabEng->PutVariable("GonioNDF", GonioNDF);
			matlabEng->PutVariable("GonioAngles_rit", GonioAngles_rit);
			matlabEng->PutVariable("GonioNDF_rit", GonioNDF_rit);
			matlabEng->PutVariable("FitDataAngles", FitAGGXAngles);
			matlabEng->PutVariable("FitDataNDFs", FitAGGXNDF);
			matlabEng->PutVariable("FitDataAngles_B", FitBeckmannAngles);
			matlabEng->PutVariable("FitDataNDFs_B", FitBeckmannNDF);
			matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
			//matlabEng->EvalString("figure;");
			matlabEng->EvalString("clf;");
			matlabEng->EvalString("clear Plot1DNDF_Angle;");
			matlabEng->EvalString("Plot1DNDF_Angle(ProfilAngles,ProfilNDF,GonioAngles,GonioNDF,GonioAngles_rit,GonioNDF_rit,FitDataAngles,FitDataNDFs,FitDataAngles_B,FitDataNDFs_B,strDesc);");

			mxDestroyArray(ProfilAngles);
			mxDestroyArray(ProfilNDF);
			mxDestroyArray(GonioAngles);
			mxDestroyArray(GonioNDF);
			mxDestroyArray(GonioAngles_rit);
			mxDestroyArray(GonioNDF_rit);
			mxDestroyArray(FitAGGXAngles);
			mxDestroyArray(FitAGGXNDF);
			mxDestroyArray(FitBeckmannAngles);
			mxDestroyArray(FitBeckmannNDF);
			//release resources
			SAFE_RELEASE(pd3dImmediateContext);
			SAFE_RELEASE(pTexLargeNDF);

	}
}


void CMFCD3D11TestView::OnEditComputendfmultiplefiles8by8()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		int iMaxNumFiles = 10;
		TCHAR* strFilesNamesGroup = new TCHAR[MAX_PATH*iMaxNumFiles];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*MAX_PATH*iMaxNumFiles);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = 256;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle=50;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT;// | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			int iPos = strSelectedFiles.ReverseFind(_T('\\'));
			CString strFileNames = strSelectedFiles.Mid(iPos+1);
			CString strFileFolderPath = strSelectedFiles.TrimRight(strFileNames);
			strFileNames.TrimLeft();strFileNames.TrimRight();

			bool bFinished = false;
			//Get filtering method and sigma from GUI
			//
			NORMALESTIMATEMETHOD iCurNFMethod;
			int iKernelSize = 0;
			float fCurGaussSigma = 0.0f;

			queryXYZNormEstParamsFromUI(iCurNFMethod,iKernelSize,fCurGaussSigma);

			//temporarily fixed!!!
			float fSampleWidth = 440;
			float fSampleHeight = 330;

			CString strOutput(_T("Start Generate NDF from multiple files:"));
			theApp.OutputString(strOutput);
			//clear array
			m_arrNDFCumulation_LargeRegion.clear();
			int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();
			for (int j = 0; j < i2DNDFImgDim; j++)
				for (int i = 0; i < i2DNDFImgDim; i++)
					m_arrNDFCumulation_LargeRegion.push_back(0.0);	
			while (!bFinished)
			{
				CString strSingleFN;
				int iPos1 = strFileNames.Find(_T(' '));
				if(iPos1 >= 0)
					strSingleFN = strFileNames.Left(iPos1);
				else
				{
					strSingleFN = strFileNames;
					bFinished = true;
				}
				strFileNames.TrimLeft(strSingleFN);
				strFileNames.TrimLeft();
				CString strSingleFileFullPath = strFileFolderPath + strSingleFN;

				//theApp.OutputString(strSingleFileFullPath);
				//process each file!
				CXYZFileIO* pSingleXYZFile = new CXYZFileIO();
				//load files
				if(pSingleXYZFile->LoadFromFile(CT2A(strSingleFileFullPath),fSampleWidth,fSampleHeight) < 0)
					return;
				//temporarily change the members 
				pSingleXYZFile->m_iCurNormalEstiMethod = iCurNFMethod;
				pSingleXYZFile->m_fSigma = fCurGaussSigma;

				//estimate normals
				if(!pSingleXYZFile->EstimateNormalForEachPointNoAccumulation())
					return;
				//accumulation Normal
				ComputeNDFCumulationArray_Largeregion(pSingleXYZFile);

				//delete
				SAFE_DELETE(pSingleXYZFile);
				strOutput.Format(_T("%s processed!"), strSingleFileFullPath);
				theApp.OutputString(strOutput);
			}

			//normalization
			double fNormalizeFactor = 0;
			int iNumPixelsInCircle = ceil(i2DNDFImgDim*i2DNDFImgDim*(D3DX_PI/4.0));
			double fProjectSAPerPixel = (D3DX_PI/iNumPixelsInCircle);
			for (int j = 0; j < i2DNDFImgDim; j++)
				for(int i = 0; i < i2DNDFImgDim; i++)
				{
					float fVal = m_arrNDFCumulation_LargeRegion[j*i2DNDFImgDim+i];
					if( fVal > 0) //>0, otherwise no contribution
						fNormalizeFactor += fVal*fProjectSAPerPixel;
				}

				//normalization
				//and save matlab fitting data (.mfd)
				CString strMFDFullPath(strFileFolderPath);
				CString strTableFilePath(strFileFolderPath);
				strMFDFullPath.Append(_T("LargeRegion_2DNDF.mfd"));
				strTableFilePath.Append(_T("LargeRegion_2DNDF.txt"));


				FILE* fp = NULL;
				_tfopen_s(&fp,(LPCTSTR)strMFDFullPath,_T("w"));
				FILE* fp1 = NULL;
				_tfopen_s(&fp1,(LPCTSTR)strTableFilePath,_T("w"));
				fwprintf(fp1,_T("%d %d\n"),i2DNDFImgDim,i2DNDFImgDim);

				for (int j = 0; j < i2DNDFImgDim; j++)
					for(int i = 0; i < i2DNDFImgDim; i++)
					{
						int idx = j*i2DNDFImgDim+i;
						m_arrNDFCumulation_LargeRegion[idx] /= fNormalizeFactor;

						//save .mfd file
						if(m_arrNDFCumulation_LargeRegion[idx] > 0.1)
						{
							float fThetaM = 0.0f, fPhiM = 0.0f;
							CD3DUtilityFunction::Convert2DPosTo2Angles(i,j,i2DNDFImgDim,i2DNDFImgDim,fThetaM,fPhiM);
							fwprintf(fp,_T("%f %f %f\n"),fThetaM,fPhiM,m_arrNDFCumulation_LargeRegion[idx]);
							fwprintf(fp1,_T("%f "),m_arrNDFCumulation_LargeRegion[idx]);
						}
						else
							fwprintf(fp1,_T("0 "));
						//
						if(i == i2DNDFImgDim-1)
							fwprintf(fp1,_T("\n"));
					}
					fclose(fp);
					fclose(fp1);

					//save 2d ndf image
					HRESULT hr = S_OK;

					//Generate 2D normal histogram image
					CString strNHImgFullPath(strFileFolderPath);
					strNHImgFullPath.Append(_T("LargeRegion_2DNDF.bmp"));
					//SAVE BMP 
					ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();

					//hr = CD3DUtilityFunction::SaveNDFImage_Gray(pd3dDevice,strNHImgFullPath,m_i2DNDFImgDim,m_i2DNDFImgDim,m_arrNDFCumulation);
					hr = CD3DUtilityFunction::SaveNDFImage(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);
					//SAVE DDS file
					strNHImgFullPath.TrimRight(_T(".bmp"));
					strNHImgFullPath.Append(_T(".dds"));
					hr = CD3DUtilityFunction::SaveNDFFloatImageData(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,m_arrNDFCumulation_LargeRegion);

					if(hr == S_OK) 
					{
						CString strTmp;
						strTmp.Format(_T("%s Generated!"), strNHImgFullPath);
						theApp.OutputString(strTmp);
					}

		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
}


void CMFCD3D11TestView::OnEditSplitinaarbitrarysize()
{
	// TODO: Add your command handler code here
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		int iNumRowPerPiece = 1000;
		int iNumColPerPiece = 1000;
		
		bool bRt = pXYZFile->SplitXYZFilesArbitrarySize(iNumRowPerPiece, iNumColPerPiece);
		if(!bRt)
		{
			CString output(_T("Split files Failed!!!"));
			theApp.OutputString(output);
		}
	}
}


void CMFCD3D11TestView::OnEditSaveasobjfile()
{
	// TODO: Add your command handler code here
	//prepare the string to show the neighbor size and sigma value
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		bool bRt = pXYZFile->SaveOBJFile();
		if(!bRt)
		{
			CString output(_T("Save OBJFile Failed!!!"));
			theApp.OutputString(output);
		}
	}
}

LRESULT CMFCD3D11TestView::OnLoadXYZProcessing(WPARAM wParam, LPARAM lparam)
{
	m_lPercentDisplay = wParam;
	//Invalidate(FALSE);
	return 0;
}

LRESULT CMFCD3D11TestView::OnLoadXYZFinished(WPARAM,LPARAM)
{
	m_lPercentDisplay = 100;
	//Invalidate(FALSE);
	SetXYZFileLoadStatus(true);

	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return -1;

	//set up 2d heightmap bmp
	UtilityString strHBMPFN(pDoc->GetXYZFile()->m_strXYZFileName);
	strHBMPFN.replaceExt("bmp");
	m_dlg2dHeightBMP.SetBitmap(strHBMPFN.GetWCharStr());

	pDoc->ProcessXYZFile();

	//start process xyz file

	return 0;
}

LRESULT CMFCD3D11TestView::OnLoadXYZStarted(WPARAM,LPARAM)
{
	SetXYZFileLoadStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnComputeWBRDFSingleXYZStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnComputeWBRDFMultipleXYZStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnProcessXYZStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnProcessMXYZStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnNormEstUpdateStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnRTVGonioMFilesStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}


LRESULT CMFCD3D11TestView::OnRTVGonioMFilesFinished(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnRTVGonioStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnRTVGonioFinished(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnRTHMStatStarted(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(false);
	return 0;
}

LRESULT CMFCD3D11TestView::OnRTHMStatFinished(WPARAM,LPARAM)
{
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnNormEstUpdateFinished(WPARAM,LPARAM)
{
	ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();
	HRESULT hr = m_D3DWnd.GetRenderHMTech()->prepareNormalLineVB(pd3dDevice);
	if(hr!=S_OK)
		return 0;

	m_D3DWnd.GetRenderHMTech()->SetDataStatus(true);
	CString strTmp;
	strTmp.Format(_T("New Normal Estimation Params Applied!\n"));
	theApp.OutputString(strTmp);

	m_dlg2DNDFVisual.SetBitmap((LPCTSTR)m_dlg2DNDFVisual.m_wndBMP.GetCurNDFFileFullName());
	//set bool
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnComputeWBRDFMultipleXYZFinished(WPARAM,LPARAM)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return -1;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile) {

		//save wBRDF data
		//save wBRDF data file!
		if(pXYZFile->m_arrWaveOpticBRDF_MFiles.size() > 0) 
		{
			//prepare initial folder
			CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
			int iPos = strInitFolder.ReverseFind('\\');
			CString strXYZFileName = strInitFolder.Mid(iPos+1);
			strInitFolder.TrimRight(strXYZFileName);	

			//save the wBRDF data
			OPENFILENAME spf;
			ZeroMemory( &spf, sizeof(spf));
			//maximumlly 10 files
			const DWORD iMaxNumFiles = 1;
			const DWORD fileNameMaxLength = MAX_PATH + 1;
			const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
			TCHAR* strFileName = new TCHAR[bufferSize];
			memset(strFileName,0,sizeof(TCHAR)*bufferSize);

			spf.hwndOwner = 0;
			spf.lpstrFilter = L"TXT Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
			spf.lpstrCustomFilter = 0;
			spf.nMaxCustFilter = 0L;
			spf.nFilterIndex = 1L;
			spf.lpstrFile = strFileName;
			spf.nMaxFile = bufferSize;
			spf.lpstrFileTitle = 0;
			spf.nMaxFileTitle= 0;
			spf.lpstrInitialDir = (LPCTSTR)strInitFolder;
			spf.lpstrTitle = L"Open .txt Files";
			spf.nFileOffset = 0;
			spf.nFileExtension = 0;
			spf.lpstrDefExt = L"*.txt";
			spf.lpfnHook = NULL;
			spf.lCustData = 0;
			spf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_HIDEREADONLY;
			spf.lStructSize = sizeof(OPENFILENAME);

			if(GetSaveFileName(&spf))
			{
				FILE* fp1 = NULL;
				_tfopen_s(&fp1,(const TCHAR*)(spf.lpstrFile), L"w");

				for (size_t iWBrdf = 0;  iWBrdf < pXYZFile->m_arrWaveOpticBRDF_MFiles.size(); iWBrdf++)
					_ftprintf(fp1,L"fHalfAng=%f wBRDF=%lf\n",pXYZFile->m_arrWaveOpticBRDF_MFiles[iWBrdf].m_fThetaM, pXYZFile->m_arrWaveOpticBRDF_MFiles[iWBrdf].BRDFVal);

				fclose(fp1);
			}
			SAFE_DELETE_ARRAY(strFileName);
		}

		//if no gonio data read, read it!
		if(!pXYZFile->PrepareGonioData())
				return -1;
		//plot data
		CMatlabEng* matlabEng = theApp.GetMATLABEngine();
		if(!matlabEng)
			return -1;
		//Angle data
		CGrowableArray<double> arrAngles;
		//Gonio BRDF 
		CGrowableArray<double> arrGonioBRDF;
		//Wave optic BRDF
		CGrowableArray<double> arrWaveBRDF;

		size_t iNumBRDFData = pXYZFile->m_arrWaveOpticBRDF_MFiles.size();
		for (size_t iAng = 0; iAng < iNumBRDFData; iAng++) {
			arrAngles.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].m_fThetaM);
			arrWaveBRDF.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].BRDFVal);
			arrGonioBRDF.Add(pXYZFile->m_GonioData.m_arrBRDFData[iAng].m_fBRDF);			
		}

		mxArray *marrAngles = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrWaveBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrWaveBRDF), (void *)arrWaveBRDF.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrGonioBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrGonioBRDF), (void *)arrGonioBRDF.GetData(), sizeof(double)*iNumBRDFData);

		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "Comparison Between Gonio BRDF and Wave Optic BRDF (Multiple Files)");
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
		/*
		* Place the variable T into the MATLAB workspace
		*/
		matlabEng->PutVariable("arrAngles", marrAngles);
		matlabEng->PutVariable("arrWaveBRDF", marrWaveBRDF);
		matlabEng->PutVariable("arrGonioBRDF", marrGonioBRDF);
		matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
		//matlabEng->EvalString("figure;");
		matlabEng->EvalString("clf;");
		matlabEng->EvalString("clear PlotBRDFComp_Wave;");
		matlabEng->EvalString("PlotBRDFComp_Wave(arrAngles,arrWaveBRDF,arrGonioBRDF, strDesc);");

		mxDestroyArray(marrAngles);
		mxDestroyArray(marrWaveBRDF);
		mxDestroyArray(marrGonioBRDF);
	}
	//set bool
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnComputeWBRDFSingleXYZFinished(WPARAM,LPARAM)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return -1;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile) {
		//plot data
		CMatlabEng* matlabEng = theApp.GetMATLABEngine();
		if(!matlabEng)
			return -1;
		//Angle data
		CGrowableArray<double> arrAngles;
		//Gonio BRDF 
		CGrowableArray<double> arrGonioBRDF;
		//Wave optic BRDF
		CGrowableArray<double> arrWaveBRDF;

		size_t iNumBRDFData = pXYZFile->m_arrWaveOpticBRDF.size();
		for (size_t iAng = 0; iAng < iNumBRDFData; iAng++) {
			arrAngles.Add(pXYZFile->m_arrWaveOpticBRDF[iAng].m_fThetaM);
			arrWaveBRDF.Add(pXYZFile->m_arrWaveOpticBRDF[iAng].BRDFVal);
			arrGonioBRDF.Add(pXYZFile->m_GonioData.m_arrBRDFData[iAng].m_fBRDF);			
		}

		mxArray *marrAngles = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrWaveBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrWaveBRDF), (void *)arrWaveBRDF.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrGonioBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrGonioBRDF), (void *)arrGonioBRDF.GetData(), sizeof(double)*iNumBRDFData);

		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "Comparison Between Gonio BRDF and Wave Optic BRDF");
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
		/*
		* Place the variable T into the MATLAB workspace
		*/
		matlabEng->PutVariable("arrAngles", marrAngles);
		matlabEng->PutVariable("arrWaveBRDF", marrWaveBRDF);
		matlabEng->PutVariable("arrGonioBRDF", marrGonioBRDF);
		matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
		//matlabEng->EvalString("figure;");
		matlabEng->EvalString("clf;");
		matlabEng->EvalString("clear PlotBRDFComp_Wave;");
		matlabEng->EvalString("PlotBRDFComp_Wave(arrAngles,arrWaveBRDF,arrGonioBRDF, strDesc);");

		mxDestroyArray(marrAngles);
		mxDestroyArray(marrWaveBRDF);
		mxDestroyArray(marrGonioBRDF);
	}
	//set bool
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnProcessXYZFinished(WPARAM,LPARAM)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return -1;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
		m_D3DWnd.SetXYZFilePointer(pXYZFile);

	//load the 2D NDF image
	CString strXYZFileFullName(pXYZFile->GetStrXYZFilePathName());
	int iPos = strXYZFileFullName.ReverseFind('\\');
	CString strXYZFileFolder = strXYZFileFullName.Mid(0,iPos+1);
	CString strXYZFileName = strXYZFileFullName.Right(strXYZFileFullName.GetLength() - strXYZFileFolder.GetLength());
	iPos = strXYZFileName.ReverseFind('.');
	CString strXYZFileOnlyName = strXYZFileName.Mid(0,iPos);
	strXYZFileOnlyName.Append(_T("_2DNDF.bmp"));
	CString strNDFBMPFileName = strXYZFileFolder + strXYZFileOnlyName;
	m_dlg2DNDFVisual.SetBitmap((LPCTSTR)strNDFBMPFileName);

	//set bool
	SetXYZFileProcessStatus(true);
	return 0;
}

LRESULT CMFCD3D11TestView::OnProcessMXYZFinished(WPARAM,LPARAM)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return -1;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		int i2DNDFImgDim = pXYZFile->GetCur2DNDFImgDim();
		std::vector<double>& arrNDFCumulationL = pXYZFile->m_arrNDFCumulation_LargeRegion;
		//normalization
		double fProjectSAPerPixel = (4.0)/(i2DNDFImgDim*i2DNDFImgDim);
		double fNormalizeFactor = 0;
		for (int j = 0; j < i2DNDFImgDim; j++)
			for(int i = 0; i < i2DNDFImgDim; i++)
			{
				double fVal = arrNDFCumulationL[j*i2DNDFImgDim+i];
				if( fVal > 0) //>0, otherwise no contribution
					fNormalizeFactor += fVal*fProjectSAPerPixel;
			}

			//normalization
			//and save matlab fitting data (.mfd)
			CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
			int iPos = strInitFolder.ReverseFind('\\');
			CString strXYZFileName = strInitFolder.Mid(iPos+1);
			strInitFolder.TrimRight(strXYZFileName);	

			CString strMFDFullPath(strInitFolder);
			CString strTableFilePath(strInitFolder);
			strMFDFullPath.Append(_T("LargeRegion_2DNDF.mfd"));
			strTableFilePath.Append(_T("LargeRegion_2DNDF.txt"));


			FILE* fp = NULL;
			_tfopen_s(&fp,(LPCTSTR)strMFDFullPath,_T("w"));
			FILE* fp1 = NULL;
			_tfopen_s(&fp1,(LPCTSTR)strTableFilePath,_T("w"));
			fwprintf(fp1,_T("%d %d\n"),i2DNDFImgDim,i2DNDFImgDim);

			for (int j = 0; j < i2DNDFImgDim; j++)
				for(int i = 0; i < i2DNDFImgDim; i++)
				{
					int idx = j*i2DNDFImgDim+i;
					arrNDFCumulationL[idx] /= fNormalizeFactor;

					//save .mfd file
					if(arrNDFCumulationL[idx] > 0.1)
					{
						float fThetaM = 0.0f, fPhiM = 0.0f;
						CD3DUtilityFunction::Convert2DPosTo2Angles(i,j,i2DNDFImgDim,i2DNDFImgDim,fThetaM,fPhiM);
						fwprintf(fp,_T("%f %f %f\n"),fThetaM,fPhiM,arrNDFCumulationL[idx]);
						fwprintf(fp1,_T("%f "),arrNDFCumulationL[idx]);
					}
					else
						fwprintf(fp1,_T("0 "));
					//
					if(i == i2DNDFImgDim-1)
						fwprintf(fp1,_T("\n"));
				}
				fclose(fp);
				fclose(fp1);

				//save 2d ndf image
				HRESULT hr = S_OK;

				//Generate 2D normal histogram image
				CString strNHImgFullPath(strInitFolder);
				strNHImgFullPath.Append(_T("LargeRegion_2DNDF.bmp"));
				//SAVE BMP 
				ID3D11Device* pd3dDevice = AfxDXGlobal()->Device();

				//hr = CD3DUtilityFunction::SaveNDFImage_Gray(pd3dDevice,strNHImgFullPath,m_i2DNDFImgDim,m_i2DNDFImgDim,m_arrNDFCumulation);
				hr = CD3DUtilityFunction::SaveNDFImage(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,arrNDFCumulationL);
				//SAVE DDS file
				strNHImgFullPath.TrimRight(_T(".bmp"));
				strNHImgFullPath.Append(_T(".dds"));
				hr = CD3DUtilityFunction::SaveNDFFloatImageData(pd3dDevice,strNHImgFullPath,i2DNDFImgDim,i2DNDFImgDim,arrNDFCumulationL);

				if(hr == S_OK) 
				{
					CString strTmp;
					strTmp.Format(_T("%s Generated!"), strNHImgFullPath);
					theApp.OutputString(strTmp);
				}

	}
	//set status, resume rendering
	SetXYZFileProcessStatus(true);
	return 0;
}

void CMFCD3D11TestView::OnEditComputendfmultiplefilesgeneral()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		const DWORD iMaxNumFiles = 1000;
		const DWORD fileNameMaxLength = MAX_PATH + 1;
		const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
		TCHAR* strFilesNamesGroup = new TCHAR[bufferSize];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*bufferSize);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = bufferSize;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle= 0;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			// enumerate the files
			LPCTSTR pFile = opf.lpstrFile;
			pFile += _tcslen(pFile);
			++pFile;        // pFile is the first name now!

			strSelectedFiles.Append(L"\\ ");
			while(*pFile)
			{
				strSelectedFiles.AppendFormat(L"%s ",pFile);
				pFile += _tcslen(pFile);
				++pFile;
			}
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			//set mfiles string
			pDoc->m_strMXYZFiles = strSelectedFiles;
			//Get filtering method and sigma from GUI
			//
			NORMALESTIMATEMETHOD iCurNFMethod;
			int iKernelSize = 0;
			float fCurGaussSigma = 0.0f; 
			queryXYZNormEstParamsFromUI(iCurNFMethod,iKernelSize,fCurGaussSigma);

			
			//Norm estimation method MFiles
			pDoc->m_iCurNormEstMethodMFiles = iCurNFMethod;
			//NF kernel size
			pDoc->m_iNFKernelSizeMFiles = iKernelSize;
			//Sigma values MFiles
			pDoc->m_fGaussSigmaMFiles = fCurGaussSigma;
			//Width and Height MFiles
			pDoc->m_fSampleWidthMFiles = 70;
			pDoc->m_fSampleHeightMfiles = 55;

			CString strOutput(_T("Start Generate NDF from multiple files:"));
			theApp.OutputString(strOutput);
			strOutput.Format(L"Gaussian Sigma = %f", fCurGaussSigma);
			theApp.OutputString(strOutput);
			//Generate NDF from MFiles
			//
			pDoc->EstimateNormMFiles();

		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
}

void CMFCD3D11TestView::SetNormalWndSize(int iSize)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	pDoc->SetNormalWndSize(iSize);
}

void CMFCD3D11TestView::SetNFGaussianSigma(float fSigma)
{
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	pDoc->SetNFGaussianSigma(fSigma);
}

void CMFCD3D11TestView::OnEditShow2dheightmapbmp()
{
	// TODO: Add your command handler code here
	m_dlg2dHeightBMP.ShowWindow(SW_SHOW);
}


void CMFCD3D11TestView::OnEditPlot1dsliceheightY()
{
	// TODO: Add your control notification handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	float fHeight = pDoc->GetXYZFile()->m_fSampleHeight;
	int iXDim = pDoc->GetXYZFile()->m_iHMDataWidth;
	int iYDim = pDoc->GetXYZFile()->m_iHMDataHeight;

	m_iCurHeightBMPDir = Y_DIR;

	Plot1DSliceHeight(theApp.GetMATLABEngine(),m_dlg2dHeightBMP.m_wndBMP.Get1DSlicePoints_Y(), fHeight, iYDim,iXDim);
}


void CMFCD3D11TestView::OnEditPlot1dsliceheightX()
{
	// TODO: Add your control notification handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	float fWidth = pDoc->GetXYZFile()->m_fSampleWidth;
	int iXDim = pDoc->GetXYZFile()->m_iHMDataWidth;
	int iYDim = pDoc->GetXYZFile()->m_iHMDataHeight;

	m_iCurHeightBMPDir = X_DIR;

	Plot1DSliceHeight(theApp.GetMATLABEngine(),m_dlg2dHeightBMP.m_wndBMP.Get1DSlicePoints_X(), fWidth, iYDim,iXDim);
}


void CMFCD3D11TestView::OnRaytracingstatisticaltest()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	pDoc->RayTraceCurXYZFileStatistics();
}


void CMFCD3D11TestView::OnEditRaytracingvirtualgoniotest()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	pDoc->RaytracingVirtualGonioTest();
}


void CMFCD3D11TestView::OnEditRaytracingvirtualgoniotestMfiles()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		const DWORD iMaxNumFiles = 1000;
		const DWORD fileNameMaxLength = MAX_PATH + 1;
		const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
		TCHAR* strFilesNamesGroup = new TCHAR[bufferSize];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*bufferSize);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = bufferSize;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle= 0;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			// enumerate the files
			LPCTSTR pFile = opf.lpstrFile;
			pFile += _tcslen(pFile);
			++pFile;        // pFile is the first name now!

			strSelectedFiles.Append(L"\\ ");
			while(*pFile)
			{
				strSelectedFiles.AppendFormat(L"%s ",pFile);
				pFile += _tcslen(pFile);
				++pFile;
			}
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			//set mfiles string
			pDoc->m_strMXYZFiles = strSelectedFiles;
			theApp.OutputString(strSelectedFiles);
			int iLength = strSelectedFiles.GetLength();
			CString strLength;
			strLength.Format(L"length=%d",iLength);
			theApp.OutputString(strLength);
			//Get filtering method and sigma from GUI
			//
			CMFCPropertyGridProperty* pRTHMProperty = theApp.GetPropertyGridCtrl()->GetProperty(4);
			
			CMFCPropertyGridProperty* pfRTHMScaleRatio = pRTHMProperty->GetSubItem(0);
			int iScaleVal = pfRTHMScaleRatio->GetValue().intVal;
			float fScaleRatio = (float)(iScaleVal)/100.0f;
			pDoc->setRTScaleRatio(fScaleRatio);

			
			CMFCPropertyGridProperty* pfRTHMThetaAng = pRTHMProperty->GetSubItem(1);
			int iRTThetaAng = pfRTHMThetaAng->GetValue().intVal;
			pDoc->setRTThetaAng(static_cast<float>(iRTThetaAng));


			CMFCPropertyGridProperty* pfRTHMPhiAng = pRTHMProperty->GetSubItem(2);
			int iRTPhiAng = pfRTHMPhiAng->GetValue().intVal;
			pDoc->setRTPhiAng(static_cast<float>(iRTPhiAng));
			
			//Width and Height MFiles
			pDoc->m_fSampleWidthMFiles = 70;
			pDoc->m_fSampleHeightMfiles = 55;

			//Virtual Gonio from MFiles
			//
			pDoc->RaytracingVirtualGonioTest_MFiles();

		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
}


void CMFCD3D11TestView::OnEditShow2dndfplotLargeregion()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pCurXYZFile = pDoc->GetXYZFile();
	if(pCurXYZFile){
		UtilityString strXYZFileFullPath(pCurXYZFile->m_strXYZFileName);
		UtilityString strXYZFileName("LargeRegion_2DNDF.bmp");
		strXYZFileFullPath.Remove1LevelSubDirectory();
		strXYZFileFullPath.ConcatenateStr("\\");
		strXYZFileFullPath.ConcatenateUtilityStr(strXYZFileName);
		m_dlg2DNDFVisual.SetBitmap(static_cast<LPCTSTR>(strXYZFileFullPath.GetWCharStr()));
		m_dlg2DNDFVisual.ShowWindow(SW_SHOW);
	}	
}


void CMFCD3D11TestView::OnEditDebugsincoswave()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//create a temporary xyz file
		CXYZFileIO* pEllipsoidXYZ = new CXYZFileIO();
		//set parameters
		UtilityString strEllipsoidFN(pDoc->GetXYZFile()->GetStrXYZFilePathName());
		strEllipsoidFN.Remove1LevelSubDirectory();
		strEllipsoidFN.ConcatenateStr("\\");

		pEllipsoidXYZ->m_iHMDataWidth = pXYZFile->m_iHMDataWidth;
		pEllipsoidXYZ->m_iHMDataHeight = pXYZFile->m_iHMDataHeight;

		pEllipsoidXYZ->m_arrHeightMapData = new float[pEllipsoidXYZ->m_iHMDataWidth*pEllipsoidXYZ->m_iHMDataHeight];

		pEllipsoidXYZ->m_fSampleWidth = 70;
		pEllipsoidXYZ->m_fSampleHeight = 55;

		//generate positions firstly!
        unsigned int iNumWave = 4;

		//CD3DUtilityFunction::fill2DHMWithSinCosWave(iNumWave, pEllipsoidXYZ->m_iHMDataWidth, pEllipsoidXYZ->m_iHMDataHeight,-0.5,-0.5,
			//pEllipsoidXYZ->m_fSampleWidth, pEllipsoidXYZ->m_fSampleHeight, pEllipsoidXYZ->m_arrVertices);
		CD3DUtilityFunction::fill2DHMWithSinCosWave_Irregular(iNumWave,1, 8.0f, pEllipsoidXYZ->m_iHMDataWidth, pEllipsoidXYZ->m_iHMDataHeight,-0.5,-0.5,
				pEllipsoidXYZ->m_fSampleWidth, pEllipsoidXYZ->m_fSampleHeight, pEllipsoidXYZ->m_arrVertices);
		//CD3DUtilityFunction::fill2DHMWithEllipsoidEq(a_x, a_y, fRadiusX, fRadiusY, pEllipsoidXYZ->m_iHMDataWidth, pEllipsoidXYZ->m_iHMDataHeight, 
		//	                                         pEllipsoidXYZ->m_arrVertices);
		////refill heightmap array
		for (int j = 0; j < pEllipsoidXYZ->m_iHMDataHeight; j++)
			for (int i = 0; i < pEllipsoidXYZ->m_iHMDataWidth; i++){
				int iIdx = j * pEllipsoidXYZ->m_iHMDataWidth + i;
				pEllipsoidXYZ->m_arrHeightMapData[iIdx] = pEllipsoidXYZ->m_arrVertices[iIdx].Position.z;
			}
		//assign some parameters
			//start loading file
			/*line 1*/
			//string constant 
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strConstL1,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strConstL1, pXYZFile->m_strConstL1);
			/*line 2*/
			pEllipsoidXYZ->m_iSoftwareType = pXYZFile->m_iSoftwareType;
			pEllipsoidXYZ->m_iMajorVers = pXYZFile->m_iMajorVers;
			pEllipsoidXYZ->m_iMinorVers = pXYZFile->m_iMinorVers;
			pEllipsoidXYZ->m_iBugVers = pXYZFile->m_iBugVers;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strSoftwareDate,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strSoftwareDate, pXYZFile->m_strSoftwareDate);
			/*line 3*/
			pEllipsoidXYZ->m_iIntensOriginX = pXYZFile->m_iIntensOriginX;
			pEllipsoidXYZ->m_iIntensOriginY = pXYZFile->m_iIntensOriginY;
			pEllipsoidXYZ->m_iNBuckets = pXYZFile->m_iNBuckets;
			pEllipsoidXYZ->m_uiIntensRange = pXYZFile->m_uiIntensRange;			
			/*line 4*/
			pEllipsoidXYZ->m_iPhaseOriginX = pXYZFile->m_iPhaseOriginX;
			pEllipsoidXYZ->m_iPhaseOriginY = pXYZFile->m_iPhaseOriginY;
			/*line 5*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strComment,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strComment, pXYZFile->m_strComment);			
			/*line 6*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strPartSerNum,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strPartSerNum, pXYZFile->m_strPartSerNum);						
			/*line 7*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strPartNum,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strPartNum, pXYZFile->m_strPartNum);									
			/*line 8*/
			pEllipsoidXYZ->m_iSource = pXYZFile->m_iSource;
			pEllipsoidXYZ->m_fIntfScaleFactor = pXYZFile->m_fIntfScaleFactor;
			pEllipsoidXYZ->m_fWavelengthIn = pXYZFile->m_fWavelengthIn;
			pEllipsoidXYZ->m_fNumericAperture = pXYZFile->m_fNumericAperture;
			pEllipsoidXYZ->m_fObliquityFactor = pXYZFile->m_fObliquityFactor;
			pEllipsoidXYZ->m_fMagnification = pXYZFile->m_fMagnification;
			pEllipsoidXYZ->m_fCameraRes = pXYZFile->m_fCameraRes;
			pEllipsoidXYZ->m_iTimeStamp = pXYZFile->m_iTimeStamp;			
			/*line 9*/
			pEllipsoidXYZ->m_iSystemType = pXYZFile->m_iSystemType;
			pEllipsoidXYZ->m_iSystemBoard = pXYZFile->m_iSystemBoard;
			pEllipsoidXYZ->m_iSystemSerial = pXYZFile->m_iSystemSerial;
			pEllipsoidXYZ->m_iInstrumentId = pXYZFile->m_iInstrumentId;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strObjectiveName,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strObjectiveName, pXYZFile->m_strObjectiveName);				
			/*line 10*/
			pEllipsoidXYZ->m_iAcquireMode = pXYZFile->m_iAcquireMode;
			pEllipsoidXYZ->m_iIntensAvgs = pXYZFile->m_iIntensAvgs;
			pEllipsoidXYZ->m_iPZTCal = pXYZFile->m_iPZTCal;
			pEllipsoidXYZ->m_iPZTGain = pXYZFile->m_iPZTGain;
			pEllipsoidXYZ->m_iPZTGainTolerance = pXYZFile->m_iPZTGainTolerance;
			pEllipsoidXYZ->m_iAGC = pXYZFile->m_iAGC;
			pEllipsoidXYZ->m_fTargetRange = pXYZFile->m_fTargetRange;
			pEllipsoidXYZ->m_fLightLevel = pXYZFile->m_fLightLevel;
			pEllipsoidXYZ->m_iMinMod = pXYZFile->m_iMinMod;
			pEllipsoidXYZ->m_iMinModPts = pXYZFile->m_iMinModPts;
			/*line 11*/
			pEllipsoidXYZ->m_iPhaseRes = pXYZFile->m_iPhaseRes;
			pEllipsoidXYZ->m_iPhaseAvgs = pXYZFile->m_iPhaseAvgs;
			pEllipsoidXYZ->m_iMinimumAreaSize = pXYZFile->m_iMinimumAreaSize;
			pEllipsoidXYZ->m_iDisconAction = pXYZFile->m_iDisconAction;
			pEllipsoidXYZ->m_fDisconFilter = pXYZFile->m_fDisconFilter;
			pEllipsoidXYZ->m_iConnectionOrder = pXYZFile->m_iConnectionOrder;
			pEllipsoidXYZ->m_iRemoveTiltBias = pXYZFile->m_iRemoveTiltBias;
			pEllipsoidXYZ->m_iDataSign = pXYZFile->m_iDataSign;
			pEllipsoidXYZ->m_iCodeVType = pXYZFile->m_iCodeVType;
			/*line 12*/
			pEllipsoidXYZ->m_iSubtractSysErr = pXYZFile->m_iSubtractSysErr;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strSysErrFile,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strSysErrFile, pXYZFile->m_strSysErrFile);		
			/*line 13*/
			pEllipsoidXYZ->m_fRefractiveIndex = pXYZFile->m_fRefractiveIndex;
			pEllipsoidXYZ->m_fPartThickness = pXYZFile->m_fPartThickness;
			/*line 14*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strZoomDesc,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strZoomDesc, pXYZFile->m_strZoomDesc);		

		//save .xyz file
		//prepare file name
		UtilityString tmpFN;
		tmpFN.GenerateFormatSmallString("SinCosWave_iNum=%d.xyz", iNumWave);
		strEllipsoidFN.ConcatenateUtilityStr(tmpFN);

		strcpy(pEllipsoidXYZ->m_strXYZFileName, strEllipsoidFN.GetCharStr());
		bool bRt = pEllipsoidXYZ->SaveXYZFile(pEllipsoidXYZ->m_strXYZFileName, 0, pEllipsoidXYZ->m_iHMDataHeight-1, 0, pEllipsoidXYZ->m_iHMDataWidth-1);
		if(bRt){
			CString strDebug;
			strDebug.Format(L"%s is generated!", strEllipsoidFN.GetWCharStr());
			theApp.OutputString(strDebug);
		}

		//release
		SAFE_DELETE(pEllipsoidXYZ);
	}

}

void CMFCD3D11TestView::OnEditDebugndfellipsoid()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//create a temporary xyz file
		CXYZFileIO* pEllipsoidXYZ = new CXYZFileIO();
		//set parameters
		UtilityString strEllipsoidFN(pDoc->GetXYZFile()->GetStrXYZFilePathName());
		strEllipsoidFN.Remove1LevelSubDirectory();
		strEllipsoidFN.ConcatenateStr("\\");

		pEllipsoidXYZ->m_iHMDataWidth = m_iHMDataWidth;
		pEllipsoidXYZ->m_iHMDataHeight = m_iHMDataHeight;

		pEllipsoidXYZ->m_arrHeightMapData = new float[pEllipsoidXYZ->m_iHMDataWidth*pEllipsoidXYZ->m_iHMDataHeight];

		pEllipsoidXYZ->m_fSampleWidth = m_fDataPSize_x;
		pEllipsoidXYZ->m_fSampleHeight = m_fDataPSize_y;

		//generate positions firstly!
#define ELLIPSOID
#ifdef ELLIPSOID
		//float a_x = 1.0f, a_y = 1.0f/( ((float)(pEllipsoidXYZ->m_iHMDataHeight)/pEllipsoidXYZ->m_iHMDataWidth) * a_x );
		//double a_x = 0.01106, a_y = 0.2134;
		//double a_x = 0.05506, a_y = 0.2134;
		double a_x = m_fAlphaX_AGGX, a_y = m_fAlphaY_AGGX;
		//float a_x = 0.1106f, a_y = 1.134f;
		double fRadiusX = 0.5*pEllipsoidXYZ->m_fSampleWidth;
		double fRadiusY = 0.5*pEllipsoidXYZ->m_fSampleHeight;
#endif

		CD3DUtilityFunction::fill2DHMWithEllipsoidEq(a_x, a_y, fRadiusX, fRadiusY, pEllipsoidXYZ->m_iHMDataWidth, pEllipsoidXYZ->m_iHMDataHeight, 
			pEllipsoidXYZ->m_arrVertices, m_fAdjustScalingFactor);
		////refill heightmap array
		for (int j = 0; j < pEllipsoidXYZ->m_iHMDataHeight; j++)
			for (int i = 0; i < pEllipsoidXYZ->m_iHMDataWidth; i++){
				int iIdx = j * pEllipsoidXYZ->m_iHMDataWidth + i;
				pEllipsoidXYZ->m_arrHeightMapData[iIdx] = pEllipsoidXYZ->m_arrVertices[iIdx].Position.z;
			}
			//assign some parameters
			//start loading file
			/*line 1*/
			//string constant 
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strConstL1,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strConstL1, pXYZFile->m_strConstL1);
			/*line 2*/
			pEllipsoidXYZ->m_iSoftwareType = pXYZFile->m_iSoftwareType;
			pEllipsoidXYZ->m_iMajorVers = pXYZFile->m_iMajorVers;
			pEllipsoidXYZ->m_iMinorVers = pXYZFile->m_iMinorVers;
			pEllipsoidXYZ->m_iBugVers = pXYZFile->m_iBugVers;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strSoftwareDate,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strSoftwareDate, pXYZFile->m_strSoftwareDate);
			/*line 3*/
			pEllipsoidXYZ->m_iIntensOriginX = pXYZFile->m_iIntensOriginX;
			pEllipsoidXYZ->m_iIntensOriginY = pXYZFile->m_iIntensOriginY;
			pEllipsoidXYZ->m_iNBuckets = pXYZFile->m_iNBuckets;
			pEllipsoidXYZ->m_uiIntensRange = pXYZFile->m_uiIntensRange;			
			/*line 4*/
			pEllipsoidXYZ->m_iPhaseOriginX = pXYZFile->m_iPhaseOriginX;
			pEllipsoidXYZ->m_iPhaseOriginY = pXYZFile->m_iPhaseOriginY;
			/*line 5*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strComment,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strComment, pXYZFile->m_strComment);			
			/*line 6*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strPartSerNum,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strPartSerNum, pXYZFile->m_strPartSerNum);						
			/*line 7*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strPartNum,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strPartNum, pXYZFile->m_strPartNum);									
			/*line 8*/
			pEllipsoidXYZ->m_iSource = pXYZFile->m_iSource;
			pEllipsoidXYZ->m_fIntfScaleFactor = pXYZFile->m_fIntfScaleFactor;
			pEllipsoidXYZ->m_fWavelengthIn = pXYZFile->m_fWavelengthIn;
			pEllipsoidXYZ->m_fNumericAperture = pXYZFile->m_fNumericAperture;
			pEllipsoidXYZ->m_fObliquityFactor = pXYZFile->m_fObliquityFactor;
			pEllipsoidXYZ->m_fMagnification = pXYZFile->m_fMagnification;
			pEllipsoidXYZ->m_fCameraRes = pXYZFile->m_fCameraRes;
			pEllipsoidXYZ->m_iTimeStamp = pXYZFile->m_iTimeStamp;			
			/*line 9*/
			pEllipsoidXYZ->m_iSystemType = pXYZFile->m_iSystemType;
			pEllipsoidXYZ->m_iSystemBoard = pXYZFile->m_iSystemBoard;
			pEllipsoidXYZ->m_iSystemSerial = pXYZFile->m_iSystemSerial;
			pEllipsoidXYZ->m_iInstrumentId = pXYZFile->m_iInstrumentId;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strObjectiveName,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strObjectiveName, pXYZFile->m_strObjectiveName);				
			/*line 10*/
			pEllipsoidXYZ->m_iAcquireMode = pXYZFile->m_iAcquireMode;
			pEllipsoidXYZ->m_iIntensAvgs = pXYZFile->m_iIntensAvgs;
			pEllipsoidXYZ->m_iPZTCal = pXYZFile->m_iPZTCal;
			pEllipsoidXYZ->m_iPZTGain = pXYZFile->m_iPZTGain;
			pEllipsoidXYZ->m_iPZTGainTolerance = pXYZFile->m_iPZTGainTolerance;
			pEllipsoidXYZ->m_iAGC = pXYZFile->m_iAGC;
			pEllipsoidXYZ->m_fTargetRange = pXYZFile->m_fTargetRange;
			pEllipsoidXYZ->m_fLightLevel = pXYZFile->m_fLightLevel;
			pEllipsoidXYZ->m_iMinMod = pXYZFile->m_iMinMod;
			pEllipsoidXYZ->m_iMinModPts = pXYZFile->m_iMinModPts;
			/*line 11*/
			pEllipsoidXYZ->m_iPhaseRes = pXYZFile->m_iPhaseRes;
			pEllipsoidXYZ->m_iPhaseAvgs = pXYZFile->m_iPhaseAvgs;
			pEllipsoidXYZ->m_iMinimumAreaSize = pXYZFile->m_iMinimumAreaSize;
			pEllipsoidXYZ->m_iDisconAction = pXYZFile->m_iDisconAction;
			pEllipsoidXYZ->m_fDisconFilter = pXYZFile->m_fDisconFilter;
			pEllipsoidXYZ->m_iConnectionOrder = pXYZFile->m_iConnectionOrder;
			pEllipsoidXYZ->m_iRemoveTiltBias = pXYZFile->m_iRemoveTiltBias;
			pEllipsoidXYZ->m_iDataSign = pXYZFile->m_iDataSign;
			pEllipsoidXYZ->m_iCodeVType = pXYZFile->m_iCodeVType;
			/*line 12*/
			pEllipsoidXYZ->m_iSubtractSysErr = pXYZFile->m_iSubtractSysErr;
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strSysErrFile,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strSysErrFile, pXYZFile->m_strSysErrFile);		
			/*line 13*/
			pEllipsoidXYZ->m_fRefractiveIndex = pXYZFile->m_fRefractiveIndex;
			pEllipsoidXYZ->m_fPartThickness = pXYZFile->m_fPartThickness;
			/*line 14*/
			NEW_CHAR_ARRAY(pEllipsoidXYZ->m_strZoomDesc,MAX_PATH);
			strcpy(pEllipsoidXYZ->m_strZoomDesc, pXYZFile->m_strZoomDesc);		

			//save .xyz file
			//prepare file name
			UtilityString tmpFN;
			tmpFN.GenerateFormatSmallString("Ellipsoid_ax=%.3fay=%.3f.xyz", a_x, a_y);
			strEllipsoidFN.ConcatenateUtilityStr(tmpFN);

			strcpy(pEllipsoidXYZ->m_strXYZFileName, strEllipsoidFN.GetCharStr());
			bool bRt = pEllipsoidXYZ->SaveXYZFile(pEllipsoidXYZ->m_strXYZFileName, 0, pEllipsoidXYZ->m_iHMDataHeight-1, 0, pEllipsoidXYZ->m_iHMDataWidth-1);
			if(bRt){
				CString strDebug;
				strDebug.Format(L"%s is generated!", strEllipsoidFN.GetWCharStr());
				theApp.OutputString(strDebug);
			}
			//release
			SAFE_DELETE(pEllipsoidXYZ);
	}
}


void CMFCD3D11TestView::OnEditGeneratexyzfilefromafm1dslices()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		CXYZFileIO* pXYZFileAFM = new CXYZFileIO();

		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		const DWORD iMaxNumFiles = 1000;
		const DWORD fileNameMaxLength = MAX_PATH + 1;
		const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
		TCHAR* strFilesNamesGroup = new TCHAR[bufferSize];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*bufferSize);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"txt Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = bufferSize;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle= 0;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .txt Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.txt";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			// enumerate the files
			LPCTSTR pFile = opf.lpstrFile;
			pFile += _tcslen(pFile);
			++pFile;        // pFile is the first name now!

			strSelectedFiles.Append(L"\\ ");
			while(*pFile)
			{
				strSelectedFiles.AppendFormat(L"%s ",pFile);
				pFile += _tcslen(pFile);
				++pFile;
			}
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			//set mfiles string
			pDoc->m_strMAFMSliceFiles = strSelectedFiles;
			theApp.OutputString(strSelectedFiles);
			//
			//Virtual Gonio from MFiles
			//
			pDoc->GenerateHMFromAFM1DSlices(pXYZFileAFM);

			//release memory
			SAFE_DELETE(pXYZFileAFM);
		}

		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
}


void CMFCD3D11TestView::OnEditComputewaveopticsbrdf()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	pDoc->ComputeWaveOptic();
}


void CMFCD3D11TestView::OnEditComputewaveopticsbrdfMfiles()
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		const DWORD iMaxNumFiles = 1000;
		const DWORD fileNameMaxLength = MAX_PATH + 1;
		const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
		TCHAR* strFilesNamesGroup = new TCHAR[bufferSize];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*bufferSize);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = bufferSize;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle= 0;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .xyz Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.xyz";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			CString strSelectedFiles(opf.lpstrFile);
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			// enumerate the files
			LPCTSTR pFile = opf.lpstrFile;
			pFile += _tcslen(pFile);
			++pFile;        // pFile is the first name now!

			strSelectedFiles.Append(L"\\ ");
			while(*pFile)
			{
				strSelectedFiles.AppendFormat(L"%s ",pFile);
				pFile += _tcslen(pFile);
				++pFile;
			}
			strSelectedFiles.TrimLeft();
			strSelectedFiles.TrimRight();

			//set mfiles string
			pDoc->m_strMXYZFiles = strSelectedFiles;
			//Get filtering method and sigma from GUI
			//
			//Width and Height MFiles
			pDoc->m_fSampleWidthMFiles = 70;
			pDoc->m_fSampleHeightMfiles = 55;

			CString strOutput(_T("Start Compute Wave Optic BRDF from multiple files:"));
			theApp.OutputString(strOutput);
			//Generate WBRDF from MFiles
			//
			pDoc->ComputeWaveOpticMFiles();
		}
		SAFE_DELETE_ARRAY(strFilesNamesGroup);		
	}
}


void CMFCD3D11TestView::OnEditPlotwaveopticbrdfcomp()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		if(pXYZFile->m_arrWaveOpticBRDF_MFiles.size() == 0)
			return;
		//plot data
		CMatlabEng* matlabEng = theApp.GetMATLABEngine();
		if(!matlabEng)
			return;
		//Angle data
		CGrowableArray<double> arrAngles;
		//Gonio BRDF 
		CGrowableArray<double> arrGonioBRDF;
		//Wave optic BRDF
		CGrowableArray<double> arrWaveBRDF;

		//prepare gonio data
		if(!(pXYZFile->PrepareGonioData()) )
				return;
				
		size_t iNumBRDFData = pXYZFile->m_arrWaveOpticBRDF_MFiles.size();
		for (size_t iAng = 0; iAng < iNumBRDFData; iAng++) {
			arrAngles.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].m_fThetaM);
			arrWaveBRDF.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].BRDFVal);
			arrGonioBRDF.Add(pXYZFile->m_GonioData.m_arrBRDFData[iAng].m_fBRDF);			
		}

		mxArray *marrAngles = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrWaveBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrWaveBRDF), (void *)arrWaveBRDF.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrGonioBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrGonioBRDF), (void *)arrGonioBRDF.GetData(), sizeof(double)*iNumBRDFData);

		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "Comparison Between Gonio BRDF and Wave Optic BRDF");
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
		/*
		* Place the variable T into the MATLAB workspace
		*/
		matlabEng->PutVariable("arrAngles", marrAngles);
		matlabEng->PutVariable("arrWaveBRDF", marrWaveBRDF);
		matlabEng->PutVariable("arrGonioBRDF", marrGonioBRDF);
		matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
		//matlabEng->EvalString("figure;");
		matlabEng->EvalString("clf;");
		matlabEng->EvalString("clear PlotBRDFComp_Wave;");
		matlabEng->EvalString("PlotBRDFComp_Wave(arrAngles,arrWaveBRDF,arrGonioBRDF, strDesc);");

		mxDestroyArray(marrAngles);
		mxDestroyArray(marrWaveBRDF);
		mxDestroyArray(marrGonioBRDF);			
	}
}


void CMFCD3D11TestView::OnEditLoadprecomputedwaveopticbrdf()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//prepare initial folder
		CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
		int iPos = strInitFolder.ReverseFind('\\');
		CString strXYZFileName = strInitFolder.Mid(iPos+1);
		strInitFolder.TrimRight(strXYZFileName);	

		OPENFILENAME opf;
		ZeroMemory( &opf, sizeof(opf));
		//maximumlly 10 files
		const DWORD iMaxNumFiles = 1;
		const DWORD fileNameMaxLength = MAX_PATH + 1;
		const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
		TCHAR* strFilesNamesGroup = new TCHAR[bufferSize];
		memset(strFilesNamesGroup,0,sizeof(TCHAR)*bufferSize);

		opf.hwndOwner = 0;
		opf.lpstrFilter = L"txt Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = strFilesNamesGroup;
		opf.nMaxFile = bufferSize;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle= 0;
		opf.lpstrInitialDir = (LPCTSTR)strInitFolder;
		opf.lpstrTitle = L"Open .txt Files";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.txt";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER;
		opf.lStructSize = sizeof(OPENFILENAME);

		if(GetOpenFileName(&opf))
		{
			UtilityString strSelectedFile(opf.lpstrFile);
			//read the wbrdf data
			FILE* fp = fopen(strSelectedFile.GetCharStr(),"r");
			if(!fp)
				return;
			pXYZFile->m_arrWaveOpticBRDF_MFiles.clear();

			while(!feof(fp)){
				WaveOpticBRDF wBrdfData;
				fscanf(fp, "fHalfAng=%f wBRDF=%lf\n", &(wBrdfData.m_fThetaM), &(wBrdfData.BRDFVal));
				pXYZFile->m_arrWaveOpticBRDF_MFiles.push_back(wBrdfData);
			}
			fclose(fp);

			//plot data
		CMatlabEng* matlabEng = theApp.GetMATLABEngine();
		if(!matlabEng)
			return;
		//Angle data
		CGrowableArray<double> arrAngles;
		//Gonio BRDF 
		CGrowableArray<double> arrGonioBRDF;
		//Wave optic BRDF
		CGrowableArray<double> arrWaveBRDF;

		//prepare gonio data
		if(!(pXYZFile->PrepareGonioData()) )
				return;
				
		size_t iNumBRDFData = pXYZFile->m_arrWaveOpticBRDF_MFiles.size();
		for (size_t iAng = 0; iAng < iNumBRDFData; iAng++) {
			arrAngles.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].m_fThetaM);
			arrWaveBRDF.Add(pXYZFile->m_arrWaveOpticBRDF_MFiles[iAng].BRDFVal);
			arrGonioBRDF.Add(pXYZFile->m_GonioData.m_arrBRDFData[iAng].m_fBRDF);			
		}

		mxArray *marrAngles = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrAngles), (void *)arrAngles.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrWaveBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrWaveBRDF), (void *)arrWaveBRDF.GetData(), sizeof(double)*iNumBRDFData);
		mxArray *marrGonioBRDF = mxCreateDoubleMatrix(1, iNumBRDFData, mxREAL);
		memcpy((void *)mxGetPr(marrGonioBRDF), (void *)arrGonioBRDF.GetData(), sizeof(double)*iNumBRDFData);

		char strTmp[MAX_PATH];
		ZeroMemory(strTmp,sizeof(char)*MAX_PATH);
		sprintf_s( strTmp, "Comparison Between Gonio BRDF and Wave Optic BRDF");
		mxArray* strDescMat = mxCreateString(strTmp);
		matlabEng->PutVariable("strDesc", strDescMat);
		/*
		* Place the variable T into the MATLAB workspace
		*/
		matlabEng->PutVariable("arrAngles", marrAngles);
		matlabEng->PutVariable("arrWaveBRDF", marrWaveBRDF);
		matlabEng->PutVariable("arrGonioBRDF", marrGonioBRDF);
		matlabEng->EvalString("cd('C:/Users/zd/Documents/MATLAB/')");
		//matlabEng->EvalString("figure;");
		matlabEng->EvalString("clf;");
		matlabEng->EvalString("clear PlotBRDFComp_Wave;");
		matlabEng->EvalString("PlotBRDFComp_Wave(arrAngles,arrWaveBRDF,arrGonioBRDF, strDesc);");

		mxDestroyArray(marrAngles);
		mxDestroyArray(marrWaveBRDF);
		mxDestroyArray(marrGonioBRDF);

			
		}
		SAFE_DELETE_ARRAY(strFilesNamesGroup);
	}
}


void CMFCD3D11TestView::OnEditGenerateplanarxyzfile()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(pXYZFile)
	{
		//create a temporary xyz file
		CXYZFileIO* pPlanarXYZ = new CXYZFileIO();
		//set parameters
		pPlanarXYZ->m_iHMDataWidth = m_iHMDataWidth;
		pPlanarXYZ->m_iHMDataHeight = m_iHMDataHeight;

		pPlanarXYZ->m_arrHeightMapData = new float[pPlanarXYZ->m_iHMDataWidth*pPlanarXYZ->m_iHMDataHeight];

		pPlanarXYZ->m_fSampleWidth = m_fDataPSize_x;
		pPlanarXYZ->m_fSampleHeight = m_fDataPSize_y;
		//generate positions firstly!
		////refill heightmap array
		for (int j = 0; j < pPlanarXYZ->m_iHMDataHeight; j++)
			for (int i = 0; i < pPlanarXYZ->m_iHMDataWidth; i++){
				int iIdx = j * pPlanarXYZ->m_iHMDataWidth + i;
				pPlanarXYZ->m_arrHeightMapData[iIdx] = 1.0;
			}
			//assign some parameters
			//start loading file
			/*line 1*/
			//string constant 
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strConstL1,MAX_PATH);
			strcpy(pPlanarXYZ->m_strConstL1, pXYZFile->m_strConstL1);
			/*line 2*/
			pPlanarXYZ->m_iSoftwareType = pXYZFile->m_iSoftwareType;
			pPlanarXYZ->m_iMajorVers = pXYZFile->m_iMajorVers;
			pPlanarXYZ->m_iMinorVers = pXYZFile->m_iMinorVers;
			pPlanarXYZ->m_iBugVers = pXYZFile->m_iBugVers;
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strSoftwareDate,MAX_PATH);
			strcpy(pPlanarXYZ->m_strSoftwareDate, pXYZFile->m_strSoftwareDate);
			/*line 3*/
			pPlanarXYZ->m_iIntensOriginX = pXYZFile->m_iIntensOriginX;
			pPlanarXYZ->m_iIntensOriginY = pXYZFile->m_iIntensOriginY;
			pPlanarXYZ->m_iNBuckets = pXYZFile->m_iNBuckets;
			pPlanarXYZ->m_uiIntensRange = pXYZFile->m_uiIntensRange;			
			/*line 4*/
			pPlanarXYZ->m_iPhaseOriginX = pXYZFile->m_iPhaseOriginX;
			pPlanarXYZ->m_iPhaseOriginY = pXYZFile->m_iPhaseOriginY;
			/*line 5*/
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strComment,MAX_PATH);
			strcpy(pPlanarXYZ->m_strComment, pXYZFile->m_strComment);			
			/*line 6*/
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strPartSerNum,MAX_PATH);
			strcpy(pPlanarXYZ->m_strPartSerNum, pXYZFile->m_strPartSerNum);						
			/*line 7*/
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strPartNum,MAX_PATH);
			strcpy(pPlanarXYZ->m_strPartNum, pXYZFile->m_strPartNum);									
			/*line 8*/
			pPlanarXYZ->m_iSource = pXYZFile->m_iSource;
			pPlanarXYZ->m_fIntfScaleFactor = pXYZFile->m_fIntfScaleFactor;
			pPlanarXYZ->m_fWavelengthIn = pXYZFile->m_fWavelengthIn;
			pPlanarXYZ->m_fNumericAperture = pXYZFile->m_fNumericAperture;
			pPlanarXYZ->m_fObliquityFactor = pXYZFile->m_fObliquityFactor;
			pPlanarXYZ->m_fMagnification = pXYZFile->m_fMagnification;
			pPlanarXYZ->m_fCameraRes = pXYZFile->m_fCameraRes;
			pPlanarXYZ->m_iTimeStamp = pXYZFile->m_iTimeStamp;			
			/*line 9*/
			pPlanarXYZ->m_iSystemType = pXYZFile->m_iSystemType;
			pPlanarXYZ->m_iSystemBoard = pXYZFile->m_iSystemBoard;
			pPlanarXYZ->m_iSystemSerial = pXYZFile->m_iSystemSerial;
			pPlanarXYZ->m_iInstrumentId = pXYZFile->m_iInstrumentId;
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strObjectiveName,MAX_PATH);
			strcpy(pPlanarXYZ->m_strObjectiveName, pXYZFile->m_strObjectiveName);				
			/*line 10*/
			pPlanarXYZ->m_iAcquireMode = pXYZFile->m_iAcquireMode;
			pPlanarXYZ->m_iIntensAvgs = pXYZFile->m_iIntensAvgs;
			pPlanarXYZ->m_iPZTCal = pXYZFile->m_iPZTCal;
			pPlanarXYZ->m_iPZTGain = pXYZFile->m_iPZTGain;
			pPlanarXYZ->m_iPZTGainTolerance = pXYZFile->m_iPZTGainTolerance;
			pPlanarXYZ->m_iAGC = pXYZFile->m_iAGC;
			pPlanarXYZ->m_fTargetRange = pXYZFile->m_fTargetRange;
			pPlanarXYZ->m_fLightLevel = pXYZFile->m_fLightLevel;
			pPlanarXYZ->m_iMinMod = pXYZFile->m_iMinMod;
			pPlanarXYZ->m_iMinModPts = pXYZFile->m_iMinModPts;
			/*line 11*/
			pPlanarXYZ->m_iPhaseRes = pXYZFile->m_iPhaseRes;
			pPlanarXYZ->m_iPhaseAvgs = pXYZFile->m_iPhaseAvgs;
			pPlanarXYZ->m_iMinimumAreaSize = pXYZFile->m_iMinimumAreaSize;
			pPlanarXYZ->m_iDisconAction = pXYZFile->m_iDisconAction;
			pPlanarXYZ->m_fDisconFilter = pXYZFile->m_fDisconFilter;
			pPlanarXYZ->m_iConnectionOrder = pXYZFile->m_iConnectionOrder;
			pPlanarXYZ->m_iRemoveTiltBias = pXYZFile->m_iRemoveTiltBias;
			pPlanarXYZ->m_iDataSign = pXYZFile->m_iDataSign;
			pPlanarXYZ->m_iCodeVType = pXYZFile->m_iCodeVType;
			/*line 12*/
			pPlanarXYZ->m_iSubtractSysErr = pXYZFile->m_iSubtractSysErr;
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strSysErrFile,MAX_PATH);
			strcpy(pPlanarXYZ->m_strSysErrFile, pXYZFile->m_strSysErrFile);		
			/*line 13*/
			pPlanarXYZ->m_fRefractiveIndex = pXYZFile->m_fRefractiveIndex;
			pPlanarXYZ->m_fPartThickness = pXYZFile->m_fPartThickness;
			/*line 14*/
			NEW_CHAR_ARRAY(pPlanarXYZ->m_strZoomDesc,MAX_PATH);
			strcpy(pPlanarXYZ->m_strZoomDesc, pXYZFile->m_strZoomDesc);		

			//save .xyz file
			//prepare file name
			//save the wBRDF data
			//prepare initial folder
			CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
			int iPos = strInitFolder.ReverseFind('\\');
			CString strXYZFileName = strInitFolder.Mid(iPos+1);
			strInitFolder.TrimRight(strXYZFileName);	

			OPENFILENAME spf;
			ZeroMemory( &spf, sizeof(spf));
			//maximumlly 10 files
			const DWORD iMaxNumFiles = 1;
			const DWORD fileNameMaxLength = MAX_PATH + 1;
			const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
			TCHAR* strFileName = new TCHAR[bufferSize];
			memset(strFileName,0,sizeof(TCHAR)*bufferSize);

			spf.hwndOwner = 0;
			spf.lpstrFilter = L"XYZ Files (*.xyz)\0*.xyz\0All Files (*.*)\0*.*\0";
			spf.lpstrCustomFilter = 0;
			spf.nMaxCustFilter = 0L;
			spf.nFilterIndex = 1L;
			spf.lpstrFile = strFileName;
			spf.nMaxFile = bufferSize;
			spf.lpstrFileTitle = 0;
			spf.nMaxFileTitle= 0;
			spf.lpstrInitialDir = (LPCTSTR)strInitFolder;
			spf.lpstrTitle = L"Save .xyz Files";
			spf.nFileOffset = 0;
			spf.nFileExtension = 0;
			spf.lpstrDefExt = L"*.xyz";
			spf.lpfnHook = NULL;
			spf.lCustData = 0;
			spf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_HIDEREADONLY;
			spf.lStructSize = sizeof(OPENFILENAME);

			if(GetSaveFileName(&spf))
			{
				UtilityString strPlanarXYZFN(spf.lpstrFile);

				bool bRt = pPlanarXYZ->SaveXYZFile((char*)(strPlanarXYZFN.GetCharStr()), 0, pPlanarXYZ->m_iHMDataHeight-1, 0, pPlanarXYZ->m_iHMDataWidth-1);
				if(bRt){
					CString strDebug;
					strDebug.Format(L"%s is generated!", strPlanarXYZFN.GetWCharStr());
					theApp.OutputString(strDebug);
				}
			}
			SAFE_DELETE_ARRAY(strFileName);
			//release
			SAFE_DELETE(pPlanarXYZ);
	}
}


void CMFCD3D11TestView::OnEditRaytracing1dsliceseg()
{
	// TODO: Add your command handler code here
	CMFCD3D11TestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	
	CXYZFileIO* pXYZFile = pDoc->GetXYZFile();
	if(!pXYZFile)
		return;

	//prepare initial folder
	CString strInitFolder(pXYZFile->GetStrXYZFilePathName());
	int iPos = strInitFolder.ReverseFind('\\');
	CString strXYZFileName = strInitFolder.Mid(iPos+1);
	strInitFolder.TrimRight(strXYZFileName);	
	
	
	int iXDim = pDoc->GetXYZFile()->m_iHMDataWidth;
	int iYDim = pDoc->GetXYZFile()->m_iHMDataHeight;
	CGrowableArray<double> arr1DPos;
	CGrowableArray<double> arrHeightVals;
	
	float fLenth = 0;
	if(m_iCurHeightBMPDir == Y_DIR) {
		fLenth = pDoc->GetXYZFile()->m_fSampleHeight;
		Prepare1DSliceHeightData(arr1DPos, arrHeightVals, m_dlg2dHeightBMP.m_wndBMP.Get1DSlicePoints_Y(), fLenth, iYDim, iXDim);		
	} else if (m_iCurHeightBMPDir == X_DIR) {
		fLenth = pDoc->GetXYZFile()->m_fSampleWidth;
		Prepare1DSliceHeightData(arr1DPos, arrHeightVals, m_dlg2dHeightBMP.m_wndBMP.Get1DSlicePoints_X(), fLenth, iYDim, iXDim);
	}
	
	//prepare 1d height map slice line segments
	CGrowableArray<LineSeg2D> arr1DLineSegs;
	for (int iPt = 0; iPt < arr1DPos.GetSize()-1; iPt++){
		LineSeg2D segline;
		segline.vStartPt.x = static_cast<float>(arr1DPos[iPt]) - 0.5f*fLenth;
		segline.vStartPt.y = static_cast<float>(arrHeightVals[iPt]);

		segline.vEndPt.x = static_cast<float>(arr1DPos[iPt+1]) - 0.5f*fLenth;
		segline.vEndPt.y = static_cast<float>(arrHeightVals[iPt+1]);

		//compute normal
		segline.computeNorm2D();

		arr1DLineSegs.Add(segline);

		//CString strDebug;
		//strDebug.Format(L"startPt:(%f,%f), endPt:(%f,%f).", 
			//segline.vStartPt.x, segline.vStartPt.y, segline.vEndPt.x, segline.vEndPt.y);
		//theApp.OutputString(strDebug);
	}
	//save out 1d slice lines!
	//Compute the 2D ray tracing!
	OPENFILENAME spf;
	ZeroMemory( &spf, sizeof(spf));
	//maximumlly 10 files
	const DWORD iMaxNumFiles = 1;
	const DWORD fileNameMaxLength = MAX_PATH + 1;
	const DWORD bufferSize = (iMaxNumFiles * fileNameMaxLength) + 1;
	TCHAR* strFileName = new TCHAR[bufferSize];
	memset(strFileName,0,sizeof(TCHAR)*bufferSize);

	spf.hwndOwner = 0;
	spf.lpstrFilter = L"TXT Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
	spf.lpstrCustomFilter = 0;
	spf.nMaxCustFilter = 0L;
	spf.nFilterIndex = 1L;
	spf.lpstrFile = strFileName;
	spf.nMaxFile = bufferSize;
	spf.lpstrFileTitle = 0;
	spf.nMaxFileTitle= 0;
	spf.lpstrInitialDir = (LPCTSTR)strInitFolder;
	spf.lpstrTitle = L"Save 1D Slice LineSegs";
	spf.nFileOffset = 0;
	spf.nFileExtension = 0;
	spf.lpstrDefExt = L"*.txt";
	spf.lpfnHook = NULL;
	spf.lCustData = 0;
	spf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_HIDEREADONLY;
	spf.lStructSize = sizeof(OPENFILENAME);

	if(GetSaveFileName(&spf))
	{
		FILE* fp = NULL;
		_tfopen_s(&fp,(const TCHAR*)(spf.lpstrFile), L"w");

		CString strDebug;
		strDebug.Format(L"Save 1D slice segments started: %s!", spf.lpstrFile);
		theApp.OutputString(strDebug);

		for (int iSeg = 0; iSeg < arr1DLineSegs.GetSize(); iSeg++){
			fprintf(fp,"%f %f %f %f\n",arr1DLineSegs[iSeg].vStartPt.x,arr1DLineSegs[iSeg].vStartPt.y,
				arr1DLineSegs[iSeg].vEndPt.x, arr1DLineSegs[iSeg].vEndPt.y);
		}		
		fclose(fp);
		strDebug.Format(L"Save 1D slice segments finished!");
		theApp.OutputString(strDebug);		
	}
	//prepare the ray tracing rays
	if (fLenth < 1e-7)
		return;

	const int iNumRays = 50;
	D3DXVECTOR2 vInitDir(0,-1);
	float fStartHeight = 40.0f;
	float fRayTLens = 1000.0f;

	CGrowableArray<Ray2D> arrInit2DRays;
	for(int iRay = 0; iRay < iNumRays; iRay++) {
		D3DXVECTOR2 origin, direction;
		origin.x = (-0.5f+(iRay+0.5)/iNumRays)*fLenth;
		origin.y = fStartHeight;
		
		direction = vInitDir;
		
		Ray2D ray;
		ray.setOrigin(origin.x, origin.y);
		ray.setDirection(direction.x, direction.y);
		ray.setTParameters(0,fRayTLens);
		arrInit2DRays.Add(ray);
	}

	//Compute the 2D ray tracing!
	ZeroMemory( &spf, sizeof(spf));
	//maximumlly 10 files
	memset(strFileName,0,sizeof(TCHAR)*bufferSize);

	spf.hwndOwner = 0;
	spf.lpstrFilter = L"TXT Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
	spf.lpstrCustomFilter = 0;
	spf.nMaxCustFilter = 0L;
	spf.nFilterIndex = 1L;
	spf.lpstrFile = strFileName;
	spf.nMaxFile = bufferSize;
	spf.lpstrFileTitle = 0;
	spf.nMaxFileTitle= 0;
	spf.lpstrInitialDir = (LPCTSTR)strInitFolder;
	spf.lpstrTitle = L"Save 1D Tracing Results";
	spf.nFileOffset = 0;
	spf.nFileExtension = 0;
	spf.lpstrDefExt = L"*.txt";
	spf.lpfnHook = NULL;
	spf.lCustData = 0;
	spf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_HIDEREADONLY;
	spf.lStructSize = sizeof(OPENFILENAME);

	if(GetSaveFileName(&spf))
	{
		FILE* fp = NULL;
		_tfopen_s(&fp,(const TCHAR*)(spf.lpstrFile), L"w");
		
		CString strDebug;
		strDebug.Format(L"1D slice tracing started: %s!", spf.lpstrFile);
		theApp.OutputString(strDebug);

		CD3DUtilityFunction::raytrace1DSlicein2D(arrInit2DRays, arr1DLineSegs, fp);
		fclose(fp);

		strDebug.Format(L"1D slice tracing is finished!");
		theApp.OutputString(strDebug);		
	}
	SAFE_DELETE_ARRAY(strFileName);
}
